今天執行通過時間范圍查詢訂單數量的sql時,想看看該時間字段是否走了索引,發現一個很有意思的問題.
首先說一下查詢是否使用了索引的方法
通過explain來查看,即將explain放在查詢的sql前面
explain SELECT * from ord_order_consume where create_time > '2020-04-01 00:00:00' and create_time < '2020-07-23 23:59:59'
查詢結果
主要說明一下紅框里邊字段的含義
table: sql所查詢的表名
type: 結果值從好到壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般來說,得保證查詢至少達到range級別,最好能達到ref,否則就可能會出現性能問題
possible_keys: sql可能用到的索引
key: sql實際用到的索引,如果是Null,說明沒有用到索引
rows: MySQL認為執行查詢時必須檢查的行數
這里有一個有意思的問題,那就是其實我的表里邊create_time字段是加了索引的,但可以看到type=ALL,說明沒有使用到索引,這是為什么呢?
開始我以為是< >符號的問題,因為我看一篇博客上說,sql語句使用< >符號,會導致全部搜索,於是我改用between...and...語法
explain SELECT * from ord_order_consume where create_time between '2020-04-01 00:00:00' and '2020-07-23 23:59:59'
查詢結果
發現type仍然是ALL,沒有使用索引,說明這里跟< >符號沒有關系
但是,當我將日期范圍調小之后
explain SELECT * from ord_order_consume where create_time > '2020-06-01 00:00:00' and create_time < '2020-07-23 23:59:59'
查詢結果
發現type變為了range,並且key也有索引的名稱,說明使用了索引
由此得出結論
當時間類型的字段存在索引時,索引是否使用與查詢到的數量大小有關
查詢到的數量大,不使用索引;
查詢到的數量小,使用索引;
至於這個數量是什么范圍,好像是有一個比例.不過我大致測了一下,如果查詢結果在兩萬左右,會使用索引,再大就不再使用索引了(這里僅做參考)
那么,導致sql語句跳過索引,直接全表搜索的情況還有哪些呢?這里簡單做個總結
1.where條件查詢語句帶or,只要帶or,即使其中的查詢條件包含有索引的字段,也會導致索引失效,除非查詢條件的字段都帶索引(注意:主鍵自帶索引,屬於唯一索引的特定類型)
explain select * from ord_order_consume where user_id = 1349813 or buss_type = 2
結果
2.對於復合索引,如果查詢條件不是第一個索引字段,那么不會使用索引
explain select * from ord_order_consume where create_time = '2020-06-01 00:00:00'
結果
explain select * from ord_order_consume where order_state = 20
結果
3.like模糊查詢,%在左邊(查了不少資料,說%在右邊不會導致索引失效,但我實踐了一下,發現也失效了,具體原因有待進一步研究)
explain select * from ord_order_consume where stake_no like '%1'
結果
4.where查詢條件字段如果是varchar類型,必須用引號引起來,否則索引失效
explain select * from ord_order_consume where stake_no = 1140290000001466
select * from ord_order_consume where stake_no = '1140290000001466'
5.索引字段上使用 != 或者 <> 不等於操作符時,索引失效
EXPLAIN SELECT * from user where age != 18
EXPLAIN SELECT * from user where age <> 18
EXPLAIN SELECT * from user where age > 17 or age < 19
6.in 和 not in 會導致索引失效
EXPLAIN SELECT * from user where age in (18,19)
EXPLAIN SELECT * from user where age not in (18,19)
7.where查詢字段進行表達式操作,索引失效
EXPLAIN SELECT * from user where age/2 = 10
EXPLAIN SELECT * from user where age = 10*2
8.where查詢字段進行函數式操作,索引失效
EXPLAIN SELECT * from user where substring(name,1,1) = '張'
9.當全表掃描速度比索引速度快時,Mysql會使用全表掃描,此時索引失效