mysql 索引使用

索引的形式

索引是以必定數據格式存儲數據的查找路徑的數據形式。mysql

這裏舉個例子:sql

最典型的就是圖書館找一本書,咱們能夠經過 「文學」 -> 「當代」 -> 「散文」 來縮小咱們要找某一本書的範圍。那麼在這裏書本的大分類、時代、小分類,就能夠做爲找書本的索引。mysql優化

索引的開銷

索引很消耗資源,不添加沒必要要的索引。這裏是由於,索引是以樹結構來存儲的,爲了加快檢索的效率,減小查詢的次數,mysql須要保證這個樹的平衡,而這須要花銷比較多的資源和時間。性能

對於寫:索引的更新每每是最主要的開銷。那麼,對於寫異常頻繁的業務,咱們能夠考慮刪除索引這種很是規的手段。優化

對於讀:索引會佔用內存跟硬盤空間。佔用內存和硬盤的同時,也加快了檢索的速度,典型的以空間換時間的作法。spa

字符串索引

1.本質上沒差異,「AAAA」 < 「AAAB」(collation)
2.LIKE是特殊的範圍查詢
3.LIKE 「ABC%」 等同於「ABC[LOWEST]」<KEY<「ABC[HIGHEST]」,因爲前綴確認,可使用索引
4.LIKE 「%ABC」沒法使用索引code

Innodb索引

1.數據按主鍵彙集。也就是說,根據主鍵能夠直接獲取數據。
2.主鍵隱藏添加在全部索引的後面,也就是說 KEY(A)等同於KEY(A,ID)blog

數據查找

下面語句可使用索引 (LAST_NAME)排序

SELECT * FROM EMPLOYEES WHERE LAST_NAME=「Smith」

下面語句可以使用索引 (DEPT,LAST_NAME)索引

SELECT * FROM EMPLOYEES WHERE LAST_NAME=「Smith」 AND DEPT=「Accounting」

索引含有多個字段

考慮有索引 (A,B,C),請留意字段的順序
如下狀況可以使用索引

A>5 //用到了(A)
A=5 AND B>6 //用到了(A,B)
A=5 AND B=6 AND C=7 //用到了(A,B,C)
A=5 AND B IN (2,3) AND C>5 //用到了(A,B,C)

如下狀況不夠使用索引

B>5
B=6 AND C=7

如下狀況只能使用到索引的部分字段

//只能用上index(A)
A>5 AND B=2   
//只能用上index(A,B)
A=5 AND B>6 AND C=2

多字段索引結論

1.索引的匹配規則是左匹配
2.有了(A,B,C),就等於同時擁有了(A)和(A,B)
3.只要索引內,開始用範圍查詢,後面的索引就失效了。

這裏注意:
IN 在 where 中,也屬於準確查詢,不會使後面索引失效。

索引用於排序

下面語句可使用索引 (SCORE)

SELECT * FROM PLAYERS ORDER BY SCORE DESC LIMIT 10

下面語句可以使用索引 (COUNTRY, SCORE)

SELECT * FROM PLAYERS WHERE COUNTRY=「US」 ORDER BY SCORE DESC LIMIT 10

多字段索引與排序

考慮有索引(A, B),留意字段順序
如下狀況可以使用索引

ORDER BY A  
A=5 ORDER BY B
ORDER BY A DESC, B DESC
A>5 ORDER BY A

如下狀況不能使用索引用於排序

ORDER BY B //第二個字段上面排序
A>5 ORDER BY B //第一個字段是範圍查詢
A IN(1,2) ORDER BY B //第一個字段是IN範圍查詢
ORDER BY A ASC, B DESC //排序字段的順序不一致

最左匹配

對於一個索引來講,裏面的索引是有前後順序的。
例如:索引(A,B,C)

系統創建索引時,mysql會這麼作:
首先,會根據 A 的值,構建索引,
在相同 A 索引下,創建 B 的索引,
在 B 相同的索引下,創建 C 的單獨索引。
再多的字段也是如此類推。

那麼

索引組內,當前索引沒法在前綴不肯定的狀況下使用當前索引。

這也就是下面這幾個語句沒法使用索引或沒法使用完整索引的緣由:

A LIKE '%aaa' //前綴不肯定,沒法使用索引
A>5 AND B=2   //前綴A不肯定,只能用到 (A),沒法用(A,B)
A IN(1,2) ORDER BY B  //只能用到 (A),沒法用(A,B)

那爲何「A=5 AND B IN (2,3) AND C>5」 能夠用到(A,B,C)呢?

實際上,mysql優化器在這裏作了優化,
查詢的時候拆分了兩次檢查索引:

A=5 AND B=2 AND C>5
A=5 AND B=3 AND C>5

那麼,在IN的範圍不太大的狀況下,能夠在很大程度上優化查詢速度。

MySQL是如何選擇索引的?

1.每次查詢動態選擇

2.估算走索引須要查詢的行數

3.根據「Cardinality」的狀態。做爲重要參考標準。大體原理是:索引重疊的程度,重疊程度越低,這個基數越大,優化器優先選取。

show index from table 執行結果

Cardinality - 圖2

此圖告訴咱們:
使用索引查找速度對比爲:customer_id > i_gid > company_id

索引策略

1.給最頻繁的語句加索引 --要總體來看,而不是一條一條語句添加
2.儘量擴展索引,而不是新增索引
3.WHERE條件跟JOIN都能用上索引是最好的,
4.新增索引後要驗證索引是否生效,是否對能提高性能

例子:
SELECT * FROM TBL WHERE A=5 AND B=6
SELECT * FROM TBL WHERE A>5 AND B=6
應該新增索引(B,A)

優化技巧

技巧1:範圍查詢改成枚舉類型

考慮索引(A,B),A 類型爲 int

//只能用到(A)索引
SELECT * FROM TBL WHERE A BETWEEN 2 AND 4 AND B=5

改成

//能夠用到整個索引
SELECT * FROM TBL WHERE A IN (2,3,4) AND B=5

技巧2:增長假的條件

考慮索引KEY (GENDER,CITY),GENDER性別爲可枚舉數據

//沒法使用索引
SELECT * FROM PEOPLE WHERE CITY=「NEW YORK」

改成

//能用索引
SELECT * FROM PEOPLE WHERE GENDER IN (「M」,」F」) AND CITY=「NEW

對於Gender, Status, Boolean 類型很是有效

技巧3:Unionizing Filesort

考慮索引KEY(A,B)

//沒法使用索引
SELECT * FROM TBL WHERE A IN (1,2) ORDER BY B LIMIT 5;

改成

//能使用索引用做排序,沒有file_sort
(SELECT * FROM TBL WHERE A=1 ORDER BY B LIMIT 5) UNION ALL
(SELECT * FROM TBL WHERE A=2 ORDER BY B LIMIT 5) ORDER BY B LIMIT 5;

Bug: order by limit

考慮索引KEY(A,B),KEY(C)

select * from tb where a=1 and b =2 order by c  limit 10

有時候不能正確的選擇索引,
會指定使用索引(C),
先排序後篩選,致使全面檢索。
這時候須要指定索引或者改成

select * from tb where a=1 and b =2 order by c+0  limit 10

EXPLAIN

關於EXPLAIN語句,能夠幫助咱們去了解一條語句的執行效率和所用到的索引,因爲太複雜,能夠去自行看官方的文檔。有空能夠繼續寫一篇文章去幫助你們理解,也幫助本身總結。

做者:簡公介 連接:https://www.jianshu.com/p/d08f16867012 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。

相關文章
相關標籤/搜索