Mysql 尽管有索引,但使用GROUP BY查询的DISTINCT COUNT速度太慢
我有以下查询,统计每周每个区域的船只数量:Mysql 尽管有索引,但使用GROUP BY查询的DISTINCT COUNT速度太慢,mysql,query-optimization,Mysql,Query Optimization,我有以下查询,统计每周每个区域的船只数量: SELECT zone, DATE_FORMAT(creation_date, '%Y%u') AS date, COUNT(DISTINCT vessel_imo) AS vessel_count FROM vessel_position WHERE zone IS NOT NULL AND creation_date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH) G
SELECT zone,
DATE_FORMAT(creation_date, '%Y%u') AS date,
COUNT(DISTINCT vessel_imo) AS vessel_count
FROM vessel_position
WHERE zone IS NOT NULL
AND creation_date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY zone, date;
该表大约有4000万行。这方面的执行计划是:
+----+-------------+-----------------+------------+-------+--------------------+------+---------+------+----------+----------+------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------+------------+-------+--------------------+------+---------+------+----------+----------+------------------------------------------+
| 1 | SIMPLE | vessel_position | NULL | range | creation_date,zone | zone | 5 | NULL | 21190904 | 50.00 | Using where; Using index; Using filesort |
+----+-------------+-----------------+------------+-------+--------------------+------+---------+------+----------+----------+------------------------------------------+
列Vesser_imo、zone和creation_date均已编制索引。主键是复合键vessel_imo、creation_date
当我查看查询配置文件时,我可以看到我花了大量时间创建排序索引
我可以做些什么来进一步改进此查询吗?这取决于筛选条件的选择性以及表结构。过滤条件是否选择了20%的行、5%、1%、0.1% 如果您的答案低于5%,则以下索引可能会有所帮助:
create index ix1_date_zone on vessel_position (creation_date, zone);
如果表中有许多和/或重列,则此选项可能仍然很慢,具体取决于筛选条件的选择性
否则,您可以尝试使用更昂贵的索引,以避免使用表,并执行以下操作:
create index ix2_date_zone_imo on vessel_position
(creation_date, zone, vessel_imo);
该索引的维护成本更高—读取、插入、更新和删除行—但对于您的select来说,它会更快
尝试这两个选项,并根据您的需要选择最佳选项。SET@mystartdate=DATE\u subcontracate,间隔12个月 选择区域、日期\u格式创建\u日期、%Y%u'作为日期, 将不同的船舶作为船舶计数 从船舶位置 其中创建日期>=@mystartdate 和区域>0 按区域、日期分组 可能会在更短的时间内提供结果,请张贴您的每一个旧的和建议的第二次运行的比较时间 请发布新的解释选择…以确认创建日期索引现在已使用
除非允许更改旧数据,否则为什么必须收集12个月的历史记录,1个月以上的数据不会更改。假设数据一旦插入,不会更改,然后构建并维护汇总表 该表将有三列:区域、周和该周的计数。在每周开始时,仅为前一周的行构建一个分区;跳过空值。然后构建一个针对该表的查询-它将非常快,因为它将获取更少的行
同时,INDEXcreation\u date,zone,Vesser\u imo作为二级索引,将使每周任务的效率相当于当前查询的52倍。2100万行中的大多数都超过一年了吗?@RolandStarke No,每个月都有大量数据。大约一百万。Mh,没有线索,也许你可以尝试将组更改为“截止日期”,区域,因为行可能是按日期排序的,而不是区域,但我认为这不会有多大作用。请发布一个显示创建表Vesser_position和B显示Vesser_position索引的文本结果,以便进行分析。这个查询运行了多长时间?您知道第一行将是一个不完全的星期,因此计数可能会有点低吗?