一、簡述 MySQL索引的最左原則指的是,當使用多列索引時,MySQL會優先使用索引中最左邊的列。如果查詢條件中包含了索引的最左列,那麼MySQL會使用這個索引來加速查詢。 更具體的描述:建立一個索引,對於索引中的欄位,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停 ...
一、簡述
- MySQL索引的最左原則指的是,當使用多列索引時,MySQL會優先使用索引中最左邊的列。如果查詢條件中包含了索引的最左列,那麼MySQL會使用這個索引來加速查詢。
- 更具體的描述:建立一個索引,對於索引中的欄位,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配。
二、實際場景
-
單一列索引:
假設有一個表
users
,其中有一個age
列,我們為這個列創建了一個索引idx_age
。如果查詢條件是WHERE age > 18
,那麼這個索引就會被用到。如果查詢條件是WHERE name = 'John'
,那麼這個索引就不會被用到,因為name
列並沒有被包含在索引中。 -
聯合索引:
假設有一個表
users
,其中有兩個列age
和name
,我們為這兩個列創建了一個聯合索引idx_age_name
。如果查詢條件是WHERE age > 18 AND name = 'John'
,那麼這個索引就會被用到,因為查詢條件中包含了索引的最左側列age
。如果查詢條件是WHERE name = 'John' AND age > 18
,那麼這個索引就不會被用到,因為查詢條件中沒有包含索引的最左側列age
。 -
首碼索引:
假設有一個表
products
,其中有一個brand
列,我們為這個列創建了一個首碼索引idx_brand_prefix
。如果查詢條件是WHERE brand LIKE 'A%'
,那麼這個索引就會被用到,因為查詢條件中包含了索引的最左側連續若幹列。如果查詢條件是WHERE brand LIKE '%A'
,那麼這個索引就不會被用到,因為查詢條件中沒有包含索引的最左側列。
三、具體例子
-
例子1:假設有一個索引
idx(a, b, c)
,其中a
是第一列,b
是第二列,c
是第三列。如果查詢條件是WHERE a = 1 AND b = 2
,那麼MySQL會使用這個索引來加速查詢。因為a
是索引中最左邊的列,它符合最左原則。但是,如果查詢條件是
WHERE b = 2 AND c = 3
,那麼MySQL不會使用idx(a, b, c)
索引,因為它不滿足最左原則。在這個情況下,MySQL可能會使用一個名為idx2(b, c)
的另一個索引來加速查詢。 -
例子2:a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的(c中有>),如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。
四、註意事項
- 查詢條件的順序很重要。查詢條件中要按照索引的最左列到最右列的順序出現,才能利用索引進行加速查詢。否則,索引就無法被用到。
- 單個字元的通配符可以使用索引。比如,查詢條件是
WHERE name LIKE 'A%'
,這樣可以利用索引進行加速查詢。但是,如果通配符出現在字元串的中間或者右側,比如WHERE name LIKE '%A'
,那麼就無法使用索引了。 - 不要在列上進行計算。如果查詢條件中含有函數或者表達式,會導致索引失效而進行全表掃描。比如,查詢條件是
WHERE YEAR(birthday) < 1990
,這樣無法使用索引進行加速查詢。正確的做法是,將函數或者表達式放到查詢條件的右側,比如WHERE birthday < '1990-01-01'
。 - 索引不會包含有NULL值的列。只要列中包含有NULL值都將不會被包含在索引中,複合索引中只要有一列含有NULL值,那麼這一列對於此複合索引就是無效的。因此在資料庫設計時不要讓欄位的預設值為NULL。
- 儘量選擇區分度高的列作為索引。區分度的公式是count(distinct col)/count(*),表示欄位不重覆的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別欄位可能在大數據面前區分度就是0。覆蓋索引是一個非常有用的工具,能夠極大的提高性能。
- 最左原則僅適用於多列索引。對於單列索引,因為它本身就是最左的列,所以不需要使用最左原則。