explain SELECT a, b, COUNT(*) FROM tbname
GROUP BY a, b
order by a DESC
limit 1
a
和 b
列已经设置联合索引, 为什么这种操作也会执行全表扫描呢?
explain SELECT a, b FROM tbname
GROUP BY a, b
order by a DESC
去掉 COUNT
和 limit
则走索引没有扫描, 这是为什么呢?
这种场景有什么优化思路呢?
表结构
CREATE TABLE `tbname` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`a` INT(11) NULL DEFAULT '0',
`b` INT(11) NULL DEFAULT '0',
PRIMARY KEY (`id`),
INDEX `testkey` (`a`, `b`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
INSERT INTO `tbname` (`a`, `b`) VALUES ('1', '1');
INSERT INTO `tbname` (`a`, `b`) VALUES ('1', '1');
INSERT INTO `tbname` (`a`, `b`) VALUES ('1', '1');
INSERT INTO `tbname` (`a`, `b`) VALUES ('1', '1');
INSERT INTO `tbname` (`a`, `b`) VALUES ('1', '1');
查询1:
explain SELECT a, b, COUNT(*) FROM tbname
GROUP BY a, b
order by a DESC
limit 1
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
| ---: | --- | --- | --- | --- | --- | --- | --- | --- | ---: | ---: | --- |
| 1 | SIMPLE | tbname | \N | index | testkey | testkey | 10 | \N | 5 | 100.00 | Using index; Using temporary; Using filesort |
查询2:
explain SELECT a, b FROM tbname
GROUP BY a, b
order by a DESC
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
| ---: | --- | --- | --- | --- | --- | --- | --- | --- | ---: | ---: | --- |
| 1 | SIMPLE | tbname | \N | range | testkey | testkey | 10 | \N | 1 | 100.00 | Using index for group-by; Using temporary; Using filesort |
表的ddl贴出来。
两次执行的截图也出来。
一起分析一下。
第一个查询。他确实使用索引排序了。但是。count(*) 他会扫描行数来做统计。所以又走索引,又扫描了全部。这索引并不是没有意义。索引省去groupby临时排序。
第二个查询。不一定是1

再补充一个额外的问题
order by a desc 这样的话,索引只对group by有效。order不行。
因为是联合索引。你可以理解一下为啥。order by a asc 才可以
注意Extra的解释
Using index for group-by; Using temporary; Using filesort