我有以下查询来计算每周每个区域中的船只数量:
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 |
+----+-------------+-----------------+------------+-------+--------------------+------+---------+------+----------+----------+------------------------------------------+
列 vessel_imo
、zone
和 creation_date
均已编入索引。主键是组合键(vessel_imo
,creation_date
)。
当我查看查询配置文件时,我可以看到我花了很多时间在 Creating sort index
上。
我能做些什么来进一步改进这个查询吗?
最佳答案
假设数据一旦插入就不会改变,然后构建并维护一个汇总表。
该表将包含三列:区域、周和该周的不同计数。在每周开始时,仅 构建前一周的行(每个区域一个;跳过NULL
)。然后构建一个针对该表的查询——它将非常快,因为它将获取更少的行。
同时,INDEX(creation_date, zone, vessel_imo)
作为二级索引,将使每周任务相当高效(大约是当前查询速度的 52 倍)。
关于mysql - 尽管有索引,但带有 GROUP BY 查询的 DISTINCT COUNT 速度太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50525193/