【mysql索引】之多列索引

第零步:簡單說一說


多列索引並不是指建立多個單列索引,而是指在多個字段建立一個索引。

在多個列上建立獨立的單列索引大部分情況下並不能提高MySQL的查詢性能,MySQL在5.0之後推出了索引合併策略(index merge),一定程度上可以使用多個單列索引來定位指定的行,但實際上更多時候說明了表上的索引建的很糟糕:

1.當數據庫服務器對多個單列索引做相交操作(intersection,通常伴有多個AND條件)時,通常意味着需要一個包含多個相關列的多列索引,而不是多個單列索引。
2.當數據庫服務器對多個單列索引做聯合操作(union,通常伴有多個OR條件)時,需要消耗大量的CPU和內存在算法緩存、排序與合併上,特別在某些索引選擇性不高、且需要合併掃描並返回大量數據的時候。

3.更重要的是,優化器不會把以上的計算成本加入到查詢成本之中,優化器只關心隨機頁面讀取,這會導致查詢成本被低估。


第一步:選擇合適的索引順序

這裏適用於B-Tree索引,因爲哈希索引並不像B-Tree那樣按順序存儲。
有一個經驗法則:將選擇性最高的列放到索引的最前列,這個法則通常情況下有用,但通常沒有避免隨機IO和排序那麼重要。當不需考慮排序和分組時,這個法則通常是很好的,但還需要留意的是值的分佈,拿sakila數據庫裏的payment表舉例(關於選擇性和sakila這裏有上一篇的鏈接【mysql索引】之前綴索引),查詢結果如圖1:
SELECT
COUNT(DISTINCT staff_id)/COUNT(*) staff_id_selectivity,
COUNT(DISTINCT customer_id)/COUNT(*) customer_id_selectivity,
COUNT(*) total
FROM payment

圖1:

可以看出customer_id的選擇性更高,因此應該把customer_id作爲多列索引的第一項,第二項是staff_id。


第二步:添加多列索引

執行下面語句即可:
ALTER TABLE payment ADD KEY `idx_customer_id_staff_id` (customer_id, staff_id);


最後需注意的一點:

上面的經驗法則對於下面的情況,需要額外的處理:
如果某個條件值得基數過大,例如一個商城網站數據庫裏customer表裏字段username爲guest(遊客)的數量太大,幾乎佔了整個表的9/10,那麼如果用索引來查詢username爲guest的用戶時,那個索引基本上是起不了作用的,這樣有可能會極大損耗服務器的性能,解決方法是在代碼層面上解決,如限制查詢username值爲guest的用戶等。





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