mysql - 尽管有索引,但带有 GROUP BY 查询的 DISTINCT COUNT 速度太慢

标签 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)
  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_imozonecreation_date 均已编入索引。主键是组合键(vessel_imocreation_date)。

当我查看查询配置文件时,我可以看到我花了很多时间在 Creating sort index 上。

我能做些什么来进一步改进这个查询吗?

最佳答案

假设数据一旦插入就不会改变,然后构建并维护一个汇总表。

该表将包含三列:区域、周和该周的不同计数。在每周开始时, 构建前一周的行(每个区域一个;跳过NULL)。然后构建一个针对该表的查询——它将非常快,因为它将获取更少的行。

同时,INDEX(creation_date, zone, vessel_imo) 作为二级索引,将使每周任务相当高效(大约是当前查询速度的 52 倍)。

关于mysql - 尽管有索引,但带有 GROUP BY 查询的 DISTINCT COUNT 速度太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50525193/

相关文章:

mysql - 如何优化查找相关性的极其缓慢的 MySQL 查询

如果使用 ORDER BY 字符串列,MySQL 查询需要很长时间才能执行

sql - 一次从大表中获取的最佳行大小

mysql - 表加入 count() 条件

java - Spring JDBC 事务副作用

MySQL将字符串转换为日期计算年龄并按年龄排序

php - 加速mysql查询

mysql - 在 mysql 中选择长文本列太慢

mysql - 谁能推荐一个原生支持多个数据库的良好数据建模工具/数据建模器?

php - 什么更快 - 数组与数据库