mysql索引經驗小結
阿新 • • 發佈:2018-12-21
mysql索引分析對於開發人員是非常有必要的,充分理解mysql的查詢索引機制,才能寫出高效穩定的應用程式。這裡記錄下,平時的mysql索引使用經驗小結,方便以後生疏了再來回顧。
測試版本5.7.16
!=是否走索引
網上的部分文章說,都有說逆向查詢條件不走索引,但是本人在測試中發現這並不是絕對的。
原文地址 https://mp.weixin.qq.com/s/EJQHJv1WJu-aglWkIUX6aA
舉例
user表有兩個欄位,id自增主鍵,name姓名(普通索引)。
user_copy表有四個欄位,id自增主鍵,name姓名(普通索引), age, sex。
執行 explain select * from user where name != ‘xuliang’;
mysql> explain select * from user where name != 'xuliang'; +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | user | NULL | index | idx_name | idx_name | 767 | NULL | 1 | 100.00 | Using where; Using index | +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+ 1 row in set, 1 warning (0.00 sec)
執行 explain select * from user_copy where name != ‘xuliang’;
mysql> explain select * from user_copy where name != 'xuliang'; +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | user_copy | NULL | ALL | idx_name | NULL | NULL | NULL | 1 | 100.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
為什麼!=查詢時一個查詢結果顯示type=index,一個顯示type=ALL呢?
因為索引的關鍵資訊儲存在葉子結點上,葉子結點儲存著索引列的全部關鍵值 和 對應行記錄的指標。在第一個例子中,因為select *
只包含兩列,主鍵id和name,在葉子結點中可以直接拿到,所以走索引全掃描。而在第二個例子中,因為select *
還包含了age,sex欄位,所以還要根據rowid去尋找對應的行記錄,個人猜測,mysql可能考慮到 != 會匹配到更多的行記錄,還不如走全表掃描。
為了進一步驗證,我們執行
explain select id,name from user_copy where name != ‘xuliang’;
mysql> explain select id,name from user_copy where name != 'xuliang';
+----+-------------+-----------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | user_copy | NULL | index | idx_name | idx_name | 767 | NULL | 1 | 100.00 | Using where; Using index |
+----+-------------+-----------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
select count(1)會走索引
explain select count(1) from t_sp_item
執行結果