优化 COUNT(DISTINCT) SQL 查询
Posted
技术标签:
【中文标题】优化 COUNT(DISTINCT) SQL 查询【英文标题】:Optimizing COUNT(DISTINCT) SQL query 【发布时间】:2017-10-03 15:56:04 【问题描述】:我有两张桌子A,B:
A 包含两列,与 B 相比,行数相对较少(千):
id, build_id (string)
B 包含三列并且有大量的行(数十万):
id, build_id (string), task_id (string)
一个给定的构建可能有很多任务。我想获得一个表格,其中包含所有构建和每个构建的最新任务 ID 以及该构建的任务数。我的查询如下:
SELECT
A.build_id,
MAX(B.id) as latest_task_id,
COUNT(DISTINCT B.task_id) AS task_count
FROM
A
LEFT OUTER JOIN
B ON B.build_id = A.build_id
GROUP BY
A.build_id
有什么办法可以优化吗? build_id 和 task_id 上已经有索引了。
更新:这是在 postgres 9.6+ 上
【问题讨论】:
哪个 postgres 版本?这很重要,因为您可以在 9.6+ 上进行优化 mysql 和 postgresql 是两种不同的产品,具有不同的 sql 实现。你用哪一个?另外,为什么需要优化查询?慢吗?如果是,它有多慢?受影响的记录数量大致是多少? 用您真正使用的数据库标记您的问题。我删除了不兼容的数据库标签。 请edit您的问题并添加使用explain (analyze, verbose, format text)
生成的执行计划。 Formatted text 请no screen shots
B.task_id 在任一表中是否唯一? (如果是这样,创建唯一索引可能会有所帮助)
【参考方案1】:
尝试在join
之前进行聚合:
SELECT A.build_id,
MAX(B.id) as latest_task_id,
COUNT(B.task_id) AS task_count
FROM A LEFT OUTER JOIN
(SELECT B.build_id, B.task_id, MAX(B.id) as id
FROM B
GROUP BY B.build_id, B.task_id
) B
ON B.build_id = A.build_id
GROUP BY A.build_id;
有时,整体聚合的算法比COUNT(DISTINCT)
更有效。
您还可以为此查询尝试在B(build_id, task_id, id)
上建立索引。
【讨论】:
这个查询加快了速度,谢谢!。然而,覆盖指数并没有帮助。以上是关于优化 COUNT(DISTINCT) SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章