謂詞條件是is null走索引嗎?
1.建立測試表
JZH@TEST>create table t (x int,y int);
Table created.
JZH@TEST>create index t_indx on t(x,y);
Index created.
JZH@TEST>insert into t values(1,1);
1 row created.
JZH@TEST>insert into t values(1,null);
1 row created.
JZH@TEST>insert into t values(null,1);
1 row created.
JZH@TEST>insert into t values(null,null);
1 row created.
JZH@TEST>commit;
Commit complete.
2.分析索引
JZH@TEST>analyze index t_indx validate structure;
Index analyzed.
JZH@TEST>create table t (x int,y int);
Table created.
JZH@TEST>create index t_indx on t(x,y);
Index created.
JZH@TEST>insert into t values(1,1);
1 row created.
JZH@TEST>insert into t values(1,null);
1 row created.
JZH@TEST>insert into t values(null,1);
1 row created.
JZH@TEST>insert into t values(null,null);
1 row created.
JZH@TEST>commit;
Commit complete.
2.分析索引
JZH@TEST>analyze index t_indx validate structure;
Index analyzed.
3.檢視資料
JZH@TEST>select count(*) from t;
COUNT(*)
----------
4
JZH@TEST>select name,lf_rows from index_stats;
NAME LF_ROWS
------------------------------ ----------
T_INDX 3
表中有4行資料,而索引只儲存了3行,還有一行null,null索引是不儲存的,因此select * from t where x is null是不走索引的,接下來看一下:
JZH@TEST>set autot traceonly
JZH@TEST>select * from t where x is null;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 52 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 52 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("X" IS NULL)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
5 recursive calls
0 db block gets
17 consistent gets
0 physical reads
0 redo size
636 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
可以看到oracle選擇了走全表掃描,只有索引列中至少有一列為not null,oracle才會選擇走過引,下面將y列修改為not null,再看執行計劃;
JZH@TEST>alter table T modify y not null;
alter table T modify y not null
*
ERROR at line 1:
ORA-02296: cannot enable (JZH.) - null values found
JZH@TEST>delete from t where y is null;
2 rows deleted.
JZH@TEST>commit;
Commit complete.
JZH@TEST>alter table T modify y not null;
Table altered.
因為Y列有null值,所以不讓修改,刪除2行null值,再修改;
再看select * from t where x is null的執行計劃;
JZH@TEST>begin
2 dbms_stats.gather_table_stats(user,'T');
3 end;
4 /
PL/SQL procedure successfully completed.
JZH@TEST>select count(*) from t;
COUNT(*)
----------
4
JZH@TEST>select name,lf_rows from index_stats;
NAME LF_ROWS
------------------------------ ----------
T_INDX 3
表中有4行資料,而索引只儲存了3行,還有一行null,null索引是不儲存的,因此select * from t where x is null是不走索引的,接下來看一下:
JZH@TEST>set autot traceonly
JZH@TEST>select * from t where x is null;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 52 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 52 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("X" IS NULL)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
5 recursive calls
0 db block gets
17 consistent gets
0 physical reads
0 redo size
636 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
可以看到oracle選擇了走全表掃描,只有索引列中至少有一列為not null,oracle才會選擇走過引,下面將y列修改為not null,再看執行計劃;
JZH@TEST>alter table T modify y not null;
alter table T modify y not null
*
ERROR at line 1:
ORA-02296: cannot enable (JZH.) - null values found
JZH@TEST>delete from t where y is null;
2 rows deleted.
JZH@TEST>commit;
Commit complete.
JZH@TEST>alter table T modify y not null;
Table altered.
因為Y列有null值,所以不讓修改,刪除2行null值,再修改;
再看select * from t where x is null的執行計劃;
JZH@TEST>begin
2 dbms_stats.gather_table_stats(user,'T');
3 end;
4 /
PL/SQL procedure successfully completed.
JZH@TEST>select * from t where x is null;
Execution Plan
----------------------------------------------------------
Plan hash value: 4058602070
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T_INDX | 1 | 5 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("X" IS NULL)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1 consistent gets
0 physical reads
0 redo size
583 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
總結:
1、謂詞是is null的也可以使用B樹索引;
2、如果索引前導列是X,那索引其他列必須至少有一列是not null才可以走索引;
Execution Plan
----------------------------------------------------------
Plan hash value: 4058602070
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T_INDX | 1 | 5 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("X" IS NULL)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1 consistent gets
0 physical reads
0 redo size
583 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
總結:
1、謂詞是is null的也可以使用B樹索引;
2、如果索引前導列是X,那索引其他列必須至少有一列是not null才可以走索引;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10271187/viewspace-1377914/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 搜尋條件設定為Is Null一定不走索引嗎?Null索引
- ORACLE SQL過濾條件是IS NULL or !=的優化OracleSQLNull優化
- 【GreatSQL最佳化器-02】索引和Sargable謂詞SQL索引
- 資料庫聚簇索引——not null條件對唯一鍵索引成為聚簇索引的影響資料庫索引Null
- 謂詞條件的資料型別隨意書寫對SQL效能影響巨大資料型別SQL
- CHECK約束中的NULL條件Null
- 【索引】反向索引--條件 範圍查詢索引
- C++謂詞C++
- 唯一索引,可以在索引列插入多個null嗎索引Null
- 【索引】反向索引--條件 範圍查詢(二)索引
- Java 8謂詞鏈Java
- Mysql索引的使用-組合索引+跳躍條件MySql索引
- 【原創】MySQL 模擬條件索引MySql索引
- java8-謂詞(predicate)Java
- 小解謂詞 access 與 filterFilter
- 【TUNE_ORACLE】列出SQL謂詞中需要建立索引的列SQL參考OracleSQL索引
- NULL與索引Null索引
- 機器學習是萬能的嗎?AI落地有哪些先決條件?機器學習AI
- 【原創】MySQL 模擬條件索引薦MySql索引
- 原子謂詞公式和合式公式公式
- where語句中多條件查詢欄位NULL與NOT NULL不確定性查詢Null
- MySQL索引條件下推的簡單測試MySql索引
- 各種索引型別發生的條件索引型別
- Mysql索引的使用 - 組合索引 + 範圍條件的處理MySql索引
- NULL 值與索引Null索引
- 【開發篇sql】 條件和表示式(三) Null詳解SQLNull
- 替代SQL語句WHERE條件中OR關鍵詞SQL
- MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!MySqlNull索引
- 索引與null(一):單列索引索引Null
- 索引與null(二):組合索引索引Null
- PHP7 ?? 與 ?: 的作用和區別(null合併運算子, null條件運算子)PHPNull
- Partition 表掃描的過程,使用key作為謂詞與使用非key值做謂詞....
- Oracle 條件索引 case when 報錯解決方案Oracle索引
- 外連線有 OR 關聯條件只能走 NL優化優化
- Oracle 在連線條件裡處理和比較 NULL 值OracleNull
- NULL 值與索引(二)Null索引
- Oracle 是分割槽表,但條件不帶分割槽條件的SQLOracleSQL
- Java條件編譯是什麼?Java編譯