神奇了,當 MySQL l查詢條件為“>=”時,竟然不走索引?
我們都知道在數據庫查詢時,索引可以極大地提高查詢效率。通常在使用的時候,都會針對頻繁查詢的關鍵字段建立索引。
比如,當以交易日期(trans_date)來查詢交易記錄時,通常會對該字段添加索引,以便在大量數據的情況下提升查詢效率。
針對trans_date字段,創建union_idx_query索引,那么在下面以trans_date為查詢條件的語句中,毫無疑問是會走索引的:
select count(1) from A; // 40000
EXPLAIN select * from A where trans_date = '20220222';
索引1
此時,我們會想當然地以為,只要創建了索引,其他情況的使用同樣會走索引。比如下面的查詢語句:
select count(1) from t_trans_log_info where trans_date > '20220122'; //11200
EXPLAIN select * from t_trans_log_info where trans_date > '20220122';
上面的查詢語句使用了”>“來進行范圍的查詢,而且trans_date字段同樣創建了索引,那么上述SQL語句是否會走索引呢?答案是不一定。
索引2
explain上述SQL語句,發現的確走了索引。
但當換一個查詢參數時:
select count(1) from t_trans_log_info where trans_date > '20220222'; //1120
EXPLAIN select * from t_trans_log_info where trans_date > '20120222';
explain的結果顯示沒有走索引,而是進行了全表掃描:
索引3
為什么同樣的查詢語句,只是查詢的參數值不同,卻會出現一個走索引,一個不走索引的情況呢?
答案很簡單:上述索引失效是因為DBMS發現全表掃描比走索引效率更高,因此就放棄了走索引。
也就是說,當Mysql發現通過索引掃描的行記錄數超過全表的10%-30%時,優化器可能會放棄走索引,自動變成全表掃描。某些場景下即便強制SQL語句走索引,也同樣會失效。
類似的問題,在進行范圍查詢(比如>、< 、>=、<=、in等條件)時往往會出現上述情況,而上面提到的臨界值根據場景不同也會有所不同。
所以,如果你在項目中采用了上述方式的查詢,又希望它能夠走索引,就需要特別注意了。通常需要添加一些其他的限制條件或用其他方式來保證索引的有效性。