如何對Mysql數據庫進行索引優化?

本文參考:數據庫索引原理及優化

索引優化策略

在對索引進行優化時,以下原則可以參考:

1. 最左前綴匹配原則:
我們在(a,b,c)字段上建了一個聯合索引,所以這個索引是先按a 再按b 再按c進行排列的,所以:
以下的查詢方式都可以用到索引

select * from table where a=1;
select * from table where a=1 and b=2;
select * from table where a=1 and b=2 and c=3;

上面三個查詢按照 (a ), (a,b ),(a,b,c )的順序都可以利用到索引,這就是最左前綴匹配。

如果查詢語句是:

select * from table where a=1 and c=3; 那麼只會用到索引a。

如果查詢語句是:

select * from table where b=2 and c=3; 因爲沒有用到最左前綴a,所以這個查詢是用戶到索引的。

如果用到了最左前綴,但是順序顛倒會用到索引碼?
比如:

select * from table where b=2 and a=1; select * from table where b=2
and a=1 and c=3;

如果用到了最左前綴而只是顛倒了順序,也是可以用到索引的,因爲mysql查詢優化器會判斷糾正這條sql語句該以什麼樣的順序執行效率最高,最後才生成真正的執行計劃。但我們還是最好按照索引順序來查詢,這樣查詢優化器就不用重新編譯了。

2. 主鍵外鍵一定要建索引

3. 對 where,on,group by,order by 中出現的列使用索引

4. 儘量選擇區分度高的列作爲索引,區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0
對較小的數據列使用索引,這樣會使索引文件更小,同時內存中也可以裝載更多的索引鍵。

**5. 索引列不能參與計算,保持列“乾淨”.**比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’)。

6. 爲較長的字符串使用前綴索引

前綴索引就是用列的前綴代替整個列作爲索引key,當前綴長度合適時,可以做到既使得前綴索引的選擇性接近全列索引,同時因爲索引key變短而減少了索引文件的大小和維護開銷。

一般來說以下情況可以使用前綴索引:

字符串列(varchar,char,text等),需要進行全字段匹配或者前匹配。也就是=‘xxx’ 或者 like ‘xxx%’
字符串本身可能比較長,而且前幾個字符就開始不相同。比如我們對中國人的姓名使用前綴索引就沒啥意義,因爲中國人名字都很短,另外對收件地址使用前綴索引也不是很實用,因爲一方面收件地址一般都是以XX省開頭,也就是說前幾個字符都是差不多的,而且收件地址進行檢索一般都是like ’%xxx%’,不會用到前匹配。相反對外國人的姓名可以使用前綴索引,因爲其字符較長,而且前幾個字符的選擇性比較高。同樣電子郵件也是一個可以使用前綴索引的字段。
前一半字符的索引選擇性就已經接近於全字段的索引選擇性。如果整個字段的長度爲20,索引選擇性爲0.9,而我們對前10個字符建立前綴索引其選擇性也只有0.5,那麼我們需要繼續加大前綴字符的長度,但是這個時候前綴索引的優勢已經不明顯,沒有太大的建前綴索引的必要了。

一些文章中也提到:
MySQL 前綴索引能有效減小索引文件的大小,提高索引的速度。但是前綴索引也有它的壞處:MySQL 不能在 ORDER BY 或 GROUP BY 中使用前綴索引,也不能把它們用作覆蓋索引(Covering Index)

7. 儘量的擴展索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可。

8. 不要過多創建索引, 權衡索引個數與DML之間關係。DML也就是插入、刪除數據操作。這裏需要權衡一個問題,建立索引的目的是爲了提高查詢效率的,但建立的索引過多,會影響插入、刪除數據的速度,因爲我們修改的表數據,索引也需要進行調整重建。

9. 對於like查詢,”%”不要放在前面
SELECT * FROM houdunwang WHERE uname LIKE ‘後盾%’ – 走索引
SELECT * FROM houdunwang WHERE uname LIKE “%後盾%” – 不走索引

10. 查詢where條件數據類型不匹配也無法使用索引
字符串與數字比較不使用索引;
CREATE TABLEa(achar(10));
EXPLAIN SELECT * FROMaWHEREa=“1” – 走索引
EXPLAIN SELECT * FROM a WHERE a=1 – 不走索引
正則表達式不使用索引,這應該很好理解,所以在SQL中很難看到regexp關鍵字

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章