聊一聊SQL最佳化

DaiWK發表於2024-08-01

晚上睡不著,腦子裡總想著一些問題,試著寫一寫對於SQL查詢最佳化的見解。

首先,資料庫有自己的查詢最佳化器,執行一條查詢SQL最佳化器會選擇最優的方式(不走索引、走索引、走哪個索引),

所以索引不是越多越好,因為建立索引需要成本,提高索引命中率是最佳化SQL的關鍵。

索引分為主鍵索引和普通索引,在Mysql資料庫的InnoDB下,索引的結構是一顆B+樹(非葉子節點存放索引,葉子節點存放資料、所有葉子節點組成一個雙向連結串列),

每一張表都有一個主鍵索引,意味著有一個主鍵索引的B+樹,建立一個普通索引同時會建立一個該索引的B+樹,和主鍵索引的不同點是,普通索引的葉子節點存放的是(索引列+主鍵ID),

如果查詢最佳化器命中主鍵索引,直接透過主鍵索引查詢出資料

如果查詢最佳化器命中該索引,查詢資料列被索引覆蓋了則直接返回,如果沒有覆蓋,則需要透過主鍵ID去查詢主鍵索引的資料,這個過程稱為回表。

如果沒有命中索引,會遍歷主鍵索引的葉子節點(全表掃描)

如何選擇合適的索引列?

適合作為索引的列:查詢條件、排序條件

不適合做索引的列:沒有作為查詢條件、唯一性太差(走索引效率不高)、更新頻繁(索引維護成本高)

組合索引的順序選擇:根據條件使用熱度來排序

如何避免索引失效?

遵循最左字首法則,比如一個組合索引(abc),要命中索引查詢條件的組合有(a、ab、abc)

避免在索引列上使用函式,這樣會使索引失效

避免使用全模糊查詢

避免使用 is (not) null

。。。。?

減少網路IO、減少回表?

禁止使用 *

連表查詢?

連表條件建立索引

小表驅動大表

業務最佳化?

舉例,深分頁可以把上一頁最大ID作為Where條件,減少掃描範圍

其他?

拉寬表,允許一些冗餘欄位,減少表連線

分庫分表

相關文章