Table A: (columns: id (integer), name (varchar), ...)
Table B: (columns: id (integer), a_id (integer), value (numeric), ...)
Table C: (columns: id (integer), a_id (integer), b_id (integer), date (date), ...)
SELECT A.name, SUM(B.value) AS total_value,
COUNT(DISTINCT C.date) AS distinct_dates
FROM A
JOIN B ON A.id = B.a_id
JOIN C ON B.id = C.b_id
WHERE C.date BETWEEN '2022-01-01' AND '2022-12-31'
GROUP BY A.name
ORDER BY total_value DESC;
即使只限于特定的日期范围,查询的执行也需要相当长的时间。相关列上有索引。
表A大约有1000万行。
表B大约有2000万行。
表C大约有5000万行。
查询执行时间随着日期范围的增大而呈指数级增长。
哪些特定的索引、查询重写或配置更改可以缩短执行时间?
在大型数据集上处理如此复杂的连接和聚合操作的替代方法是什么?
2条答案
按热度按时间dsf9zpds1#
在不知道实际数据集和数据库配置的情况下很难说。一些一般性的提示是:
A.id
、B.a_id
、B.id
、C.b_id
和C.date
)。EXPLAIN
分析您的查询:它可以帮助您了解查询将如何执行,以便您可以识别潜在的瓶颈。m4pnthwp2#
相关列上有索引
为了让这个查询快速运行,你应该在C的
date
列和它的a_id
上有一个索引,这样就可以快速地从WHERE
子句到达第一个连接。你有这个索引吗?
如果这仍然太慢,您可能需要考虑在其他表上提供覆盖索引:
最后,这一切仍然取决于您提供的日期范围以及DBMS基于此做出的决定。如果你的日期范围覆盖了C行的90%,那么全tabke扫描可能比使用索引快得多。如果您的日期范围覆盖了C行的1%甚至更少,那么遍历索引将更快。我们不知道索引变得更好的阈值,但DBMS将尽最大努力做出最佳决策。
由于表A实际上不是聚合的一部分,因此使其对DBMS明显可见可能会有所帮助。理想情况下,优化器应该看到这是同一个查询,并提出相同的执行计划,但优化器并不完美,因此提示可能会不时有所帮助。