mysql索引经验小结

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/gs_albb/article/details/83833694

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

执行结果

相关博客

猜你喜欢

转载自blog.csdn.net/gs_albb/article/details/83833694