1. 程式人生 > >mysql索引經驗小結

mysql索引經驗小結

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

執行結果

相關部落格