SELECT UserName, UserId FROM User WHERE UserName=”?”;
其中UserName有索引,UserId也有。执行上有什么区别?
6
假如你的userid是主键,原因是用的是innodb,所以当你创建username字段的索引时,其实里面也包含了主键字段userid。
假如你的userid不是主键,而userid和username分别是2个索引,那么执行上会有区别:
第一个语句直接从username索引取数。
第二个语句先从username取数,接下来可能会有2中办法,第一种是直接回表取出userid,第二种是直接从userid索引取数。
6
对
yupeigu说的更精确一些,非聚簇索引里会包含主键,假如userid是主键就不用回源表读数据,假如不是主键就只能回源表读。假如表很大,命中的记录分布很分散,那就比较惨了
8
SELECT UserName FROM User WHERE UserName=”?”;
这个肯定走 UserName 索引,并且索引中已经能够到到全部数据了,所以走完索引就好了
SELECT UserName, UserId FROM User WHERE UserName=”?”;
这个假如走 UserNme 索引,那么假如 Userid 不是主键,则索引不会包含Userid,那索引走完就还需要取 UserID 数据
假如 mysql 判断这种做法效率低于直接扫描表,则应该会直接扫描表
本人简单地测试了一下,如下:
CREATE TABLE `t` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL, KEY `id` (`id`), KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert t values(1, "a");
mysql> explain select name from t where name=”a”;
+–+–+–+–+–+–+–+–+–+–+–+–+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+–+–+–+–+–+–+–+–+–+–+–+–+
| 1 | SIMPLE | t | NULL | ref | name | name | 33 | const | 1 | 100.00 | Using index |
+–+–+–+–+–+–+–+–+–+–+–+–+
1 row in set, 1 warning (0.00 sec)
mysql> explain select id,name from t where name=”a”;
+–+–+–+–+–+–+–+–+–+–+–+–+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+–+–+–+–+–+–+–+–+–+–+–+–+
| 1 | SIMPLE | t | NULL | ref | name | name | 33 | const | 1 | 100.00 | NULL |
+–+–+–+–+–+–+–+–+–+–+–+–+
1 row in set, 1 warning (0.00 sec)