mysql 索引設計原則

劣技砖猿發表於2024-04-12

適合新增索引的情況

1.欄位的數值有唯一性的限制

索引本身可以起到約束的作用,比如唯一索引、主鍵索引都可以起到唯一性約束的,因此我們在建立資料表時,如果某個欄位時唯一的,就可以直接建立唯一性索引或主鍵索引。不要以為唯一索引影響了 insert 的速度,這個速度損耗可以忽略不計,單體高查詢速度是明顯的。

2.頻繁作為 where 查詢條件的欄位

如果某個欄位經常在(包括 insert、update、delete 的) where 條件中被使用到,那麼就需要給這個欄位建立索引。尤其是在資料量大的情況下,建立普通索引就可以大幅提高查詢效率。

3.經常 group by 和 order by 的列

索引就是讓資料按照某種順序進行儲存或檢索,因此我們使用 group by 對資料進行分組查詢,或者使用 order by 對資料進行排序的時候,就需要對分組或者排序的欄位新增索引。如果待排序的列有多個,那麼就可以在這些列上建立組合索引。

4.distinct 欄位需要建立索引

有時我們需要對某個欄位進行去重,使用 distinct,那麼對這個欄位建立索引,就能大幅提高效率。

5.多表 join 連線操作時

首先,連線表的數量儘量不要超過3張,因為每增加一張表就相當於增加了一次巢狀的迴圈,數量級增長的非常快,嚴重影響查詢效率。
其次,需要對 where 條件中的欄位建立索引,因為 where 才是對資料條件的過濾。如果在資料量非常大的情況下,沒有 where 條件過濾時非常可怕的。
最後,對用於連線的欄位進行建立索引,並且該欄位在多張表中的型別必須一致。因為如果資料型別不一致會進行隱式轉換,索引就會失效。

6.儲存長字串時建議使用字串字首建立索引

假設我們的字串很長,那儲存字串就需要佔用很大的儲存空間。在我們需要為這個字串列建立索引時,那就意味著對於的 b+ 樹種有這麼兩個問題:

  • b+ 樹索引中的記錄需要把列的完整字串儲存起來,很費時。並且字串越長,在索引中佔用的儲存空間就越大。
  • 如果 b+ 樹索引中索引列儲存的字串很長,拿在做字串比較時會佔用更多的時間。
    因此我們可以透過擷取字串前面一部分內容建立索引,這就叫字首索引。這樣在查詢記錄時雖然不能精確的定位到記錄的位置,但是能定位到相應字首所在的位置,然後根據字首相同的記錄的主鍵回表查詢完整的字串值。即節約空間又減少了字串的比較時間,還可以答題解決排序的問題。

注意:如果使用了索引列字首的方式可能會導致使用索引排序時結果出錯,只能使用檔案排序。

7.區分度高(雜湊性高)的列適合建立索引

列的基數指的是某一列中重複的個數,也就是說,在記錄行數一定的情況下,列的基數越大,該列中的數值越分散;列的基數約小,該列中的數值越集中。這個列的基數指標會直接影響我們是否能有效的利用索引,為基數太小的列建立索引的效果可能不好。
可以使用公式 select count(distinct a)/count(*) from table 計算區分度,越接近1月號,一般超過 0.33 就算是基數比較高的列了。因此,有大量重複資料的列上就不用建立索引了。

不適合新增索引的情況

1.在條件判斷中沒有使用的欄位不用建立索引

在 where、group by、order by 裡用不到的欄位不需要建立索引,索引的價值時快速定位,如果起不到定位的欄位通常是不需要建立索引的。

2.資料量小的表最好不要使用索引

如果表記錄太少,那麼時不需要建立索引的。表記錄太少的話,有沒有索引對查詢效率的影響並不大。甚至說,查詢花費的時間可能比遍歷索引的時間還要短,索引可能不會產生最佳化效果。

3.避免對經常更新的欄位建立索引

頻繁更新的欄位不一定要建立索引。因為資料更新的時候,也需要更新索引,如果索引太多,在更新索引的時候也會造成負擔,從而影響效率。
避免對經常更新的表建立過多索引,並且索引中的列儘可能少。否則,雖然提高了查詢速度,但卻降低更新表的速度。

4.不建議用無序的值作為索引

例如:身份證、UUID、MD5、HASH、無序長字串等。

5.很少使用或不使用的列無需建立索引

表中的資料被大量更新,或者資料的使用方式被改變後,原有的一些索引可能不再需要。DBA 應當定期找出這些索引,將他們刪除,從而減少索引對更新操作的影響。

6.已經有索引的列儘量避免定義冗餘或重複索引

比如某些欄位已經存在於聯合索引中了,就不在需要單獨建立索引。又或者某個欄位已經建立了唯一索引,則無需在定義一個普通索引。

補充說明

  1. 在多個欄位都要建立索引的情況下,聯合索引優於單值索引。
  2. 建立聯合索引時,使用最頻繁的列需要放到聯合索引的左側。在進行查詢時,也應該把使用最頻繁的列放在最左側。
  3. 索引是一般雙刃劍,可以提高查詢效率,但也會降低插入和更新的速度,並佔用更多的磁碟空間。
  4. 在實際工作中,我們也需要注意平衡,索引的數目不是越多越好。我們需要限制每張表上的索引數量儘量不超過 6 個。原因:
    • 每個索引都需要佔用磁碟空間,索引越多,需要的磁碟空間就越大。
    • 索引會影響 insert、delete、update 等語句的效能,因為表中的資料更改的同時,索引也會進行調整和更新,會造成負擔。
    • 最佳化器在選擇如何最佳化查詢時,會根據統一資訊對每一個可以用到的索引來進行評估,以生成一個最好的執行計劃,如果同時有很多個索引可以用於查詢,會增加 mysql 最佳化器生成執行計劃時間,降低查詢效能。

相關文章