SQL之索引優化

1 索引三大特性

索引的高度比較低:查詢快,快速定位。

索引本身能存儲列值:索引本身存儲列值(索引值+rowid),用來優化count(*),sum(索引類)等函數。

索引本身有序:優化MAX/MIN,ORDER BY等排序。

注:建議表字段儘量不爲null。因爲索引的時候字段爲null會導致索引失敗(不加索引字段 is not null排除的情況下。)

一般需要建立索引的字段

1、經常用在where語句之後的字段

2、主鍵或者外鍵

3、字段具有唯一性的時候建立唯一性索引

4、在經常需要根據範圍進行搜索的列上創建索引,因爲索引已經排序,其指定的範圍是連續的

5、返回數據佔總數的5%以內。

優點:查詢優化後變快。

缺點:建索引需要佔空間,而且需要花時間維護。更新數據需要更新索引來保持索引有序。

2 單索引優化sql

測試數據1000000條。

表t7結構

名稱        類型             是否爲空
ID          NUMBER          N
ID2         NUMBER          N
CONTENTS    VARCHAR2(1000)  N

2.1.索引存儲值優化count

 drop index idx1_t7_id2

 1.select count (*) from t7 --11.373s
 2.select count (*) from t7 where id2 is not null --11.662s
 3.select count (1) from t7 --11.186s
 4.select count (id2) from t7 --11.653

 create index idx1_t7_id2 on t7(id2)

 1.select count (*) from t7 --12.136s
 2.select count (*) from t7 where id2 is not null --0.473s
 3.select count (1) from t7 --11.778s
 4.select count (id2) from t7 --0.472s

觀察可以看出,1、3、5對應sql執行時間基本沒有變化。

但是2、4對應sql都從11秒左右提升到0.47s左右(第二次查詢達到了0.063)。時間縮短了20多倍。明顯索引列(id2)在sql語句中被使用到。

:count使用索引統計時優化時,sql中需要用到索引列,且該列值不能爲空(如果爲null,需要加is not null剔除列裏面的空值),否則索引失效。如果索引列主鍵不爲空,count(*)會用到索引。

2.2 索引存儲列值sum與avg

drop index idx1_t7_id2

select sum (id2) from t7  --11.139s
select sum (id2) from t7  where id2 is not null--12.044s

create index idx1_t7_id2 on t7(id2)

select sum (id2) from t7  --1.375s
select sum (id2) from t7  where id2 is not null--1.326s (效果等價於索引列不爲null)

sum (索引列)可以優化sum函數查詢,前提是索引列不爲null或者排除索引列的空值,avg效果一樣。

2.3索引本身有序之order by

drop index idx1_t7_id2

1.select *  from t7 order by id2 --27.176s
2.select id2 from t7  order by id2 --12.356s
3.select id,id2 from t7 order by id2 --11.529s
4.select * from t7 where id2 >0 order by id2 --27.3s
5.select * from t7 where id2 >0 and id2<10000 order by id2 --12.012s
6.select * from t7 where id2=3 order by id2 --12.3s

create index idx1_t7_id2 on t7(id2)

1.select * from t7  order by id2  --25.586s
2.select id2 from t7  order by id2 --0.452s
3.select id,id2 from t7 order by id2 --11.435s
4.select * from t7 where id2 >0 and id2<10000 order by id2 --0.032s(id2必須字段最大與最小範圍,此處只是縮小了搜索範圍,否則無效)
5.select * from t7 where id2 =3 order by id2 --0.031s

觀察會發現2,4,5對應sql執行時間變短。此時不是使用order by的排序,而是使用索引的排序。

1.返回字段只有索引字段,以索引字段進行排序。索引有效。
2.返回字段不止索引字段,以索引字段排序,此時索引字段必須在where中指定範圍(作用是縮寫範圍,個人認爲不是索引的效果)。

2.4索引有序優化max與min

drop index idx1_t7_id2 

1.select max(id2) from t7   --12.309s
2.select min(id2) from t7   --12.169s
3.select max(id2),min(id2) from t7   --12.465s
4.select a.max,b.min from (select max(id2) max from t7) a,(select min(id2) min from t7 ) b --22.573s

create index idx1_t7_id2 on t7(id2)

1.select max(id2) from t7 --0.608s
2.select min(id2) from t7   --0.436s
3.select max(id2),min(id2) from t7   --1.279s
4.select a.max,b.min from (select max(id2) max from t7) a,(select min(id2) min from t7 ) b --0.031

注:走索引時,4比3效果好。

3 組合索引優化sql

適用場景:單列查詢結果多,組合查詢結果少。(按索引創建順序生效,中間索引斷層(where條件中),左邊索引字段生效,右邊索引字段不生效)

1.需要考慮組合順序;
2.只有等值查詢是,組合索引順序不影響性能;
3.一般將等值列放在索引前面。

組合索引sql案例

1.範圍查詢時,不要使用in,應該使用範圍(>,<)

4 分區索引

如果表關聯查詢時分區條件無法使用到,此時全局索引性能會比分區索引效果好(索引高度原因)。

5 索引的失效

5.1 邏輯失效

1.索引不能存儲空值,否則索引失效。(用is not null索引字段會有效);

2.like會使索引失效,以%開頭。(但是索引開頭能確定的時候like可以用到索引);

3.order by(除非order by 後字段出現在where條件中,或者只是返回order by後的索引字段纔會索引生效);

4.對索引列進行運算將用不到索引,應該講索引列放在比較運算符的左邊(=,<,>等),運算邏輯放右邊;

5.索引列發生類型轉換;

6.條件中用or,即使其中有條件帶索引,也不會使用索引查詢;

7.對於多列索引,不是使用的第一部分,則不會使用索引;

8.組合索引的第一列沒有出現在where條件中時。

5.2 物理失效

1.move操作,需要重建索引;

2.分區表導致。

總結

由於索引的建立會造成開銷,且會使增刪改需要維護索引順序等原因。建立索引時不應該出現無用或者大量重複交叉的索引。且組合索引列不應該超過4個。索引的選擇應該建在數據量大,但是返回數據少的表。

參考

[1]粱敬彬,粱敬弘。 收穫,不止SQL優化[J].電子工業出版社,2017.6
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章