优化大型表上的 SQL 连接
Posted
技术标签:
【中文标题】优化大型表上的 SQL 连接【英文标题】:Optimizing an SQL join on large tables 【发布时间】:2012-07-10 21:32:10 【问题描述】:我正在对 PostgreSQL 数据库上的一个大表(每天 7,000,000 条新行)运行 sql 查询集合,并且在第一个视图和现在创建表时遇到了一些性能问题。我使用的大多数命令都类似于以下查询:
CREATE TABLE events_tb AS
SELECT *
FROM
(SELECT column1, column2, column3, column4, column5
FROM test_database_1
WHERE column6 = 'value1'
AND date_column > '2012-07-01'
AND date_column < '2012-07-10'
) a
INNER JOIN ( SELECT DISTINCT column1 FROM test_database_2) b
ON (a.column1 = b.column1);
有没有办法改进上述语句集合,以解决查询是针对非常大的表运行的事实?
【问题讨论】:
请告诉我们执行计划。最好作为explain analyze
上传到explain.depesz.com
您提到了“语句集合”,但我只看到一个查询?
【参考方案1】:
这应该更简单更快:
CREATE TABLE events_tb AS
SELECT column1, column2, column3, column4, column5
FROM test_database_1 t1
WHERE column6 = 'value1'
AND date_column > '2012-07-01'
AND date_column < '2012-07-10'
AND EXISTS (
SELECT 1
FROM test_database_2 t2
WHERE t2.column1 = t1.column1
);
您的方式会在新创建的表中包含两次column1
,这将导致错误消息。
EXISTS
semi-join 应该比 JOIN
或 IN
表达式快,因为它可以在第一次找到时停止执行。这对于重复项特别有用 - 从查询中的 DISTINCT
来看,您似乎拥有重复项。
【讨论】:
【参考方案2】:我对 PostgreSQL 的优化器一无所知,但您可以尝试将 INNER JOIN
替换为 IN (SELECT...)
结构:
CREATE TABLE events_tb AS
SELECT column1, column2, column3, column4, column5
FROM test_database_1
WHERE column6 = 'value1'
AND date_column > '2012-07-01'
AND date_column < '2012-07-10'
AND column1 IN ( SELECT DISTINCT column1 FROM test_database_2 )
【讨论】:
由于您将其移至IN
,因此不再需要distinct
。这可能会改善或恶化性能,具体取决于数据的情况。
date_column
和 column6
有索引吗?
IN (SELECT ...)
在 PostgreSQL 中通常不比 JOIN
快。以上是关于优化大型表上的 SQL 连接的主要内容,如果未能解决你的问题,请参考以下文章