一个表,表结构如下: CREATE TABLE “user_task” ( “id” int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘自增ID’, “parent_id” int(10) NOT NULL DEFAULT ‘0’ COMMENT ‘问题id’, “author” int(10) NOT NULL DEFAULT ‘0’ COMMENT ‘发布人pid’, “con_id” int(10) NOT NULL COMMENT ‘群组id’, “type” tinyint(2) NOT NULL DEFAULT ‘0’ COMMENT ‘类型(0 问题;1回答)’, “title” varchar(200) NOT NULL DEFAULT ” COMMENT ‘标题’, “info” varchar(500) NOT NULL DEFAULT ” COMMENT ‘文本’, “pic” text NOT NULL COMMENT ‘图片(json)’, “audio” text NOT NULL COMMENT ‘音频(json)’, “start_time” int(10) NOT NULL DEFAULT ‘0’ COMMENT ‘发布时间’, “end_time” int(10) NOT NULL DEFAULT ‘0’ COMMENT ‘截止时间’, “create_at” int(10) NOT NULL, “modify_at” timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, “isread” tinyint(3) unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘0 已读 1 未读’, PRIMARY KEY (“id”), UNIQUE KEY “idx_con_title” (“con_id”,”title”) ) ENGINE=InnoDB AUTO_INCREMENT=401 DEFAULT CHARSET=utf8
这个表一个主键+一个唯一性索引。数据量也很少。 mysql> select count(*) from user_task; +———-+ | count(*) | +———-+ | 54 | +———-+ 1 row in set (15.76 sec)
总共54条数据。 然后我们执行下面的这些sql , 请开始仔细观察。 mysql> SELECT distinct con_id FROM user_task where id in (56,57); +——–+ | con_id | +——–+ | 844 | +——–+ mysql> explain SELECT distinct con_id FROM user_task where id in (56,57); +—-+————-+———–+————+——-+———————–+———+———+——+——+———-+——————————+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +—-+————-+———–+————+——-+———————–+———+———+——+——+———-+——————————+ | 1 | SIMPLE | user_task | NULL | range | PRIMARY,idx_con_title | PRIMARY | 4 | NULL | 2 | 100.00 | Using where; Using temporary | +—-+————-+———–+————+——-+———————–+———+———+——+——+———-+——————————+
查看执行计划,走了主键索引。 mysql> SELECT distinct con_id FROM user_task where id in (56,57,58); +——–+ | con_id | +——–+ | 844 | | 785 | +——–+ 2 rows in set (17.30 sec) mysql> SELECT distinct con_id FROM user_task where id in (56,57,58,66); +——–+ | con_id | +——–+ | 844 | | 785 | +——–+ mysql> SELECT distinct con_id FROM user_task where id in (56,57,58,66,70); +——–+ | con_id | +——–+ | 844 | | 785 | +——–+ 2 rows in set (20.64 sec) mysql> SELECT distinct con_id FROM user_task where id in (56,57,58,66,70,71); Empty set (3 min 0.16 sec)
看到了没, 妖娥子在这里出现了,where 条件范围变大了, 结果却没有了,一身汗。。。。。 结果为什么会变没有了? 谁吃了这个结果? 查看执行计划, mysql> explain SELECT distinct con_id FROM user_task where id in (56,57,58,66,70,71); +—-+————-+———–+————+——-+———————–+—————+———+——+——+———-+—————————————+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +—-+————-+———–+————+——-+———————–+—————+———+——+——+———-+—————————————+ | 1 | SIMPLE | user_task | NULL | range | PRIMARY,idx_con_title | idx_con_title | 4 | NULL | 6 | 11.11 | Using where; Using index for group-by | +—-+————-+———–+————+——-+———————–+—————+———+——+——+———-+—————————————+ 1 row in set, 1 warning (0.00 sec)
发现走的是idx_con_title 索引 。 鄙视mysql: 走这个索引也无伤大雅, 干嘛把结果弄丢了? 如果改写成group by , 如下 SELECT con_id ,count(*) FROM user_task where id in (56,57,58,66,70,71) group by con_id ;
结果正常。 如果将索引idx_con_title 删除, 下面sql结果正常。 SELECT distinct con_id FROM user_task where id in (56,57,58,66,70,71);
巨坑巨坑的bug,,,,,,且在5.7.18 以及5.7.20上均出现,其他版本未测试。 目前怀疑: 问题出现mysql的优化器上面,使用另外一个索引时,执行路径不完整(错误)导致 。明天向官方提bug.
|