mysql多列索引優化
“把Where條件里面的列都建上索引”,這種說法其實是非常錯誤的!
這樣一個查詢,假設actor_id與film_id都單獨建立索引
SELECT film_id , actor_id FROM sakila.film_actor WHERE actor_id = 1 OR film_id = 1;
在老的mysql版本中,mysql對這個查詢會使用全表掃描,除非改寫成下面這樣
SELECT film_id , actor_id FROM sakila.film_actor WEHRE actor_id = 1 UNION ALL SELECT film_id , actor_id FROM sakila.film_actor WEHRE actor_id = 1 AND actor_id <> 1;
但在mysql 5.0中,查詢能夠同時使用這兩個單列索引進行掃描,并將結果進行合并,通過Explain的Extra列可以看到這點,這種算法有3個變種:
1.OR條件的聯合(union)
2.AND條件的相交(intersection)
3.組合前兩種情況的聯合與相交
詳解具體可以參考這里
索引合并策略有時候是一種優化結果,但實際上更多時候說明了表上的索引建得很糟糕:
1.當出現服務器對多個索引做相交操作時(通常有多個AND),通常意味著需要一個包含所有相關列的多列索引,而不是多個獨立的單列索引
2.當服務器需要對多個索引做聯合操作時(通常有多個OR),通常需要耗費大量CPU和內存資源在算法的緩存、排序和合并上,特別是當其中有些索引選擇性不高,對掃描返回的大量數據進行合并時
所以如果在Explain中看到有索引合并,要好好檢查以下查詢和表的結構是否已經是最優的
多列索引
顧名思義,多列索引就是將多個列作為一個索引,在一個多列B-Tree索引中,索引列的順序意味著索引首先按照最左列進行排序,然后第二列第三列等等。所以可以按照升序或者降序進行掃描,以滿足精確符合列順序的ORDER BY , GROUP BY 和 DISTINCT等子句,所以,多列索引的順序至關重要,key(列1, 列2) 和 key(列2, 列1) 這兩個多列索引很可能有巨大的性能差距
以下面查詢為栗
SELECT * FROM payment WHERE staff_id = 2 AND customer_id = 584;
是應該創建一個 key(staff_id, customer_id) 還是 key(customer_id, staff_id) ?可以跑一些查詢來確定在這個表中值的分布情況,來確定哪個列的選擇性更高
SELECT SUM(staff_id = 2), SUM(customer_id = 584) FROM payment
結果里,哪個列的數量更少,就代表選擇性更高,那個列就應該在建立時放在多列索引的最前面、最左側
不過這樣也有需要注意的地方,因為這個例子查詢的結果非常依賴具體的值(2,584),這樣會對其他條件值的查詢不公平,應該結合實際情況從全局的角度來考慮

浙公網安備 33010602011771號