如何高效地利用MySQL索引

如何高效地利用MySQL索引

爲實現MySQL的高性能,我們需要在優化索引、優化查詢、優化表結構三個方面努力,這三個方面每個都至關重要。
本文主要討論索引相關。

1、要想高效利用索引,我們首先要考慮如何正確建立索引。

(1)在經常做搜索的列上,也就是WHERE子句裏經常出現的列,考慮加上索引,加快搜索速度。

(2)唯一標識記錄的列,應該加上唯一索引,強制該列的唯一性並且加快按該列查找記錄的速度。

(3)在內連接使用的列上加上索引,最好是在內連接用到字段都加上,因爲MySQL優化器會自動地選擇連接順序,然後觀察索引的使用情況,將沒用的索引刪除即可。

(4)在需要排序的列上加上索引,因爲索引本身是按順序的組織的,它可以避免 filesort,要知道,Server層在進行排序時是在內存中進行的,非常消耗資源。

(5)可以考慮實現覆蓋索引,即根據 SELECT 的所有字段上創建聯合索引,這樣存儲引擎只用讀取索引而不用去回表查詢,極大地減少了對數據表的訪問,大大地提高了性能。

(6)對於那些選擇性很小的列,比如性別列,增加索引並不能明顯加快查詢速度,反而該索引會成爲表的累贅。

(7)對於那些定義爲text, image和bit數據類型的列不應該增加索引。這是因爲,這些列的要麼數據量相當大,要麼取值很少。

(8)當對寫性能的要求遠遠大於讀性能時,不應該創建索引。寫性能和讀性能是互相矛盾的。這是因爲,維護一個 B+Tree 成本是非常大的,對索引的寫會涉及到頁的分裂等。

(9)複合索引的幾個字段是否經常同時以AND方式出現在Where子句中?單字段查詢是否極少甚至沒有?如果是,則可以建立複合索引,否則考慮單字段索引。這還是說明,滿足查詢性能的前提下,索引越少越好。

(10)如果複合索引所包含的字段超過3個,那麼仔細考慮其必要性,考慮減少複合的字段。

(11)在用於GROUP BY的列上加上索引,避免使用臨時表。

(12)對於較長的字符列,如 char、varchar等,由於字符串的比較相對來說非常耗時,因此考慮使用前綴索引減少索引長度,或者創建自定義哈希索引,將字符串映射成整數,然後以該整數作爲索引,同時以字符串的值作爲過濾條件。

我們在創建索引時,可以根據下面原則進行簡單判斷:索引是否將相關記錄集合到了一起,從未減少了磁盤I/O,加快搜索速度?索引中數據的排列順序是否和查找的數據的排列順序一致,從而避免了Server層的排序?索引中的列是否包含了查詢中需要的全部列從而實現了覆蓋索引? 這幾個條件層層遞進,滿足得越多越好。

2、索引正確地建立了,我們還需要正確地使用它們:

(1)使用了運算符 !=,以及關鍵字not in,not exist,>,<等,總之產生的結果集很大時(也在where條件進行大範圍的選擇時),往往導致引擎不使用索引而是走全盤掃描。因爲如果使用索引會造成大量的隨機I/O,得不償失。

(2)如果對索引列進行運算,如 WHERE substr(name, 1, 3)=‘mark’,存儲引擎並不能聰明地判斷哪些索引滿足等式,因此不能使用到索引。

(3)使用到了LIKE,並且通配符在最前面時,不能使用索引。

(4)對於聯合索引 (a, b, c),如果沒用到最左列,那麼一般情況下都使用不到索引。但是,比如統計操作 count(*) where a > xxx,是可以使用到該聯合索引的。畢竟統計這類操作,它不是檢索,並不需要索引完全有序。

(5)對於聯合索引,如果某個列使用了範圍查找,那麼其右邊的列都無法作爲索引優化查詢,但是由於 ICP(Index Condition Pushdown),這些列能作爲過濾條件在存儲引擎中對數據進行過濾。

(6)如果條件中有 OR,則必須每個OR用到的字段都有索引,否則不能使用任何索引。

(7)想在聯合查詢中使用索引來避免 filesort,則關聯查詢中的ORDER BY用到的字段必須全部是第一張表(驅動表)上的。

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