in、exists與索引
這篇文章主要討論in、not in、exists、not exists什麼時候可以使得外層的主查詢用到索引。
先看例子:
suk@SUK> @D:TEMPTEST.SQL
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE ID IN (SELECT ID FROM TEST2)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=82 Bytes=213
2)
1 0 HASH JOIN (SEMI) (Cost=29 Card=82 Bytes=2132)
2 1 INDEX (FULL SCAN) OF 'IDX_TEST1' (NON-UNIQUE) (Cost=26 C
ard=82 Bytes=1066)
3 1 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=82 Bytes=106
6)
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE ID NOT IN (SELECT ID FROM TEST2)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=10 Card=4 Bytes=52)
1 0 FILTER
2 1 TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=4 Bytes=52)
3 1 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=4 Bytes=52)
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE EXISTS (SELECT 1 FROM TEST2 WHERE TEST1.ID=TEST2.ID)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=82 Bytes=213
2)
1 0 HASH JOIN (SEMI) (Cost=29 Card=82 Bytes=2132)
2 1 INDEX (FULL SCAN) OF 'IDX_TEST1' (NON-UNIQUE) (Cost=26 C
ard=82 Bytes=1066)
3 1 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=82 Bytes=106
6)
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE NOT EXISTS (SELECT 1 FROM TEST2 WHERE TEST1.ID=TEST2.ID)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=4 Bytes=52)
1 0 FILTER
2 1 TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=4 Bytes=52)
3 1 INDEX (RANGE SCAN) OF 'IDX_TEST2' (NON-UNIQUE) (Cost=1 C
ard=1 Bytes=13)
ALTER TABLE TEST1 MODIFY ID NOT NULL
表已更改。
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE ID IN (SELECT ID FROM TEST2)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=82 Bytes=213
2)
1 0 HASH JOIN (SEMI) (Cost=29 Card=82 Bytes=2132)
2 1 INDEX (FULL SCAN) OF 'IDX_TEST1' (NON-UNIQUE) (Cost=26 C
ard=82 Bytes=1066)
3 1 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=82 Bytes=106
6)
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE ID NOT IN (SELECT ID FROM TEST2)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=26 Card=4 Bytes=52)
1 0 INDEX (FULL SCAN) OF 'IDX_TEST1' (NON-UNIQUE) (Cost=26 Car
d=4 Bytes=52)
2 1 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=4 Bytes=52)
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE EXISTS (SELECT 1 FROM TEST2 WHERE TEST1.ID=TEST2.ID)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=82 Bytes=213
2)
1 0 HASH JOIN (SEMI) (Cost=29 Card=82 Bytes=2132)
2 1 INDEX (FULL SCAN) OF 'IDX_TEST1' (NON-UNIQUE) (Cost=26 C
ard=82 Bytes=1066)
3 1 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=82 Bytes=106
6)
SELECT /*+ INDEX(TEST1) */ * FROM TEST1 WHERE NOT EXISTS (SELECT 1 FROM TEST2 WHERE TEST1.ID=TEST2.ID)
執行計劃
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=26 Card=4 Bytes=52)
1 0 INDEX (FULL SCAN) OF 'IDX_TEST1' (NON-UNIQUE) (Cost=26 Car
d=4 Bytes=52)
2 1 INDEX (RANGE SCAN) OF 'IDX_TEST2' (NON-UNIQUE) (Cost=1 C
ard=1 Bytes=13)
從上面的測試不難得出結論:
單列索引:
1、如果關聯的列沒有not null約束,in和exists有可能用到索引;not in和not exists不可能用到索引
2、如果關聯的列有not null約束,in、not in、exists、not exists都有可能用到索引
組合索引:
1、如果關聯的列都沒有not null約束,in和exists有可能用到索引;not in和not exists不可能用到索引
2、如果關聯的列至少有一個列有not null約束,in、not in、exists、not exists都有可能用到索引
如果理解in、not in、exists、not exists的本質,則不難得出上面的結論。參考:
In和exists使用及效能分析(三):in和exists的效能分析
In和exists使用及效能分析(二):exists的使用
In和exists使用及效能分析(一):in的使用
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/231499/viewspace-63820/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 不要再問我 in,exists 走不走索引了索引
- [精選] SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析SQL
- EXISTS、IN、NOT EXISTS、NOT IN(zt)
- [20180928]exists與cardinality.txt
- 對線面試官:SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析面試SQL
- exists與in子查詢優化優化
- [20180808]exists and not exists.txt
- exists()、not exists() 、in()、not in()用法以及效率差異
- sql:delete if exists還是drop if exists?SQLdelete
- in、exists操作與null的一點總結Null
- 索引與null(二):組合索引索引Null
- 索引與null(一):單列索引索引Null
- In和exists使用及效能分析(二):exists的使用
- order by與索引索引
- Oralce 使用SQL中的exists 和not exists 用法詳解SQL
- In和exists使用及效能分析(三):in和exists的效能分析
- 淺談聚簇索引與非聚簇索引索引
- fs.exists 與 fs.access的區別是什麼
- PHP審計之class_exists與任意例項化漏洞PHP
- 匿名類 與 索引重建索引
- elasticsearch之exists查詢Elasticsearch
- 淺談MySQL的B樹索引與索引優化MySql索引優化
- InnoDB索引與底層原理索引
- 《PostgreSQL》 索引與最佳化SQL索引
- MongoDB慢查詢與索引MongoDB索引
- ES 文件與索引介紹索引
- sql server 索引闡述系列七 索引填充因子與碎片SQLServer索引
- Elasticsearch之索引模板index template與索引別名index aliasElasticsearch索引Index
- not in 和 not exists 比較和用法
- mysql 關於exists 和in分析MySql
- PostgreSQL中索引與CTE簡介SQL索引
- elasticsearch(三)----索引建立與刪除Elasticsearch索引
- MongoDB索引與優化詳解MongoDB索引優化
- Mysql索引的建立與刪除MySql索引
- MySQL索引與查詢優化MySql索引優化
- MySQL 表與索引設計攻略MySql索引
- 【原始碼】Redis exists命令bug分析原始碼Redis
- beego報錯 table name: `xxx` not existsGo