無陳述,直接開講:
babysitter_account表中的聯合索引如下(開發小夥伴們自建的聯合索引、您發現不妥了嗎?):
KEY `flag` (`flag`,`user_id`,`account_id`)
過去認爲:
1.SELECT account_id,weibo_id,weibo_type FROM babysitter_account WHERE user_id BETWEEN 100 and 10000 AND flag=0;
2.SELECT account_id,weibo_id,weibo_type FROM babysitter_account WHERE flag=0 AND user_id BETWEEN 100 and 10000;
第一條sql無法命中索引、第二條會命中,
但是現實情況是兩條sql命中的索引完全一樣。
因爲mysql的查詢優化器會優化sql,優化器會根據存取類型選擇合適的驅動表達式,對於這兩條sql來說驅動表達式一樣。
查詢優化器對where帶AND的查詢優化選擇規則如下:
查詢的格式爲:<condition> AND <condition>
優化的步驟:
1) 如果兩個列都沒有索引,那麼使用全表掃描。
2) 否則,如果其中一個列擁有更好的存取類型(比如,一個具有索引,另外一個沒有索引;再或者,一個是唯一索引,另外一個是非唯一索引),那麼使用該列作爲驅動表達式。
3) 否則,如果兩個列都分別擁有索引,並且兩個條件對應的存取類型是一致的,那麼選擇定義索引時的先定義的索引。
倆條件都有索引且相同,所以存取類型都一樣,並且沒有先後定義的順序,所以執行完全一樣。
PS:account_id加在聯合索引裏完全無意義,本身就是主鍵,優先命中,只有拖慢入庫的速度。