我刚创建了一个表格:
CREATE TABLE `table_test` (
`time` date NOT NULL,
`line_id` char(36) NOT NULL,
`location_id` char(36) NOT NULL,
`placement_id` char(36) NOT NULL,
`flight_id` char(36) NOT NULL,
`impressions` int(11) DEFAULT `0`,
PRIMARY KEY (`time`,`line_id`,`location_id`,`placement_id`,`flight_id`),
KEY `table_test_IDX` (`time`,`placement_id`,`line_id`,`impressions`) USING
BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
然后当我尝试执行查询时:
SELECT
time,
placement_id,
line_id,
SUM(impressions) AS totalImpress
FROM
table_test
WHERE
time BETWEEN '2017-11-01' AND '2017-11-30'
GROUP BY time , placement_id , line_id;
它始终使用Using where; Using temporary; Using filesort
,在这种情况下,我希望查询使用table_test_IDX
。
我在这里做错了什么?
非常感谢。
答案 0 :(得分:0)
如果您仔细阅读MySQL documentation以优化聚合查询,您会发现有两种方法可以优化GROUP BY
查询,即松散和紧密的索引扫描。但是,对于这些扫描中的任何一个,一个警告是选择列表中使用的唯一聚合函数是MIN
或MAX
。由于您选择了SUM
,因此无法使用这些优化。
使用可以使WHERE
子句受益的索引是有意义的,因为这可能让我们在查询计划的早期就从结果集中丢弃记录。但是,为了计算每个组的总和,MySQL必须触摸剩余表中的每个记录。没有办法解决这个问题,所以我们如何访问所有这些记录并不重要。
答案 1 :(得分:0)
我认为您使用的是UUID?将create table my_table(name text)
partition by list (lower(left(name, 1)));
更改为CHAR(36)
。更好的是将它们打包成“BINARY”(16)。 (参见http://mysql.rjweb.org/doc.php/uuid。)这会将大小从108缩小到36到16。
你说它正在使用filesort等,但它是否使用CHAR(36) CHARACTER SET ascii
?请提供PRIMARY
。
但是,为了更快地加速,请考虑构建和维护"汇总表"。 (请参阅http://mysql.rjweb.org/doc.php/summarytables。)如果每个(time,placement_id,line_id)组合在摘要表中有一行,则可以删除EXPLAIN SELECT ...
和GROUP BY
。 (如果按小时总结,你仍然需要那些。)