左连接似乎极大地阻碍了 SQL 查询性能
Posted
技术标签:
【中文标题】左连接似乎极大地阻碍了 SQL 查询性能【英文标题】:Left join appears to be hindering SQL query performance tremendously 【发布时间】:2014-10-27 04:03:18 【问题描述】:我有两张桌子:
表 A:
Name, isPair
表 B:
Name1, Name2, Status
这是我的查询:
SELECT Name
FROM A
LEFT JOIN B ON (A.Name = B.Name2)
WHERE A.isPair = 'T' AND (B.status <> 'valid' OR B.status IS NULL)
我在两个表中都有数百万行。以目前的查询速度,完成需要 3 个多月的时间。我已经适当地索引了这两个表。当我最初执行 INNER JOIN 时,只需要 10 分钟即可完成,但我发现查询没有返回不在表 B 的 Name2 列中的行,这是一个问题,因为我需要返回它们。
【问题讨论】:
你加入了一个名字,我想这将是一个 VARCHAR 或一个 CHAR 列。见***.com/questions/332300/… 除了@rurouni88 ...“适当地索引两个表”是什么意思? @rurouni88 谢谢,但这不是缓慢的主要原因。我之前已经将这两个表与其他表进行了多次连接,查询时间不到 10 分钟。 @TeamTam 我已经索引了这些表。名称是唯一的。 这将有助于比较查询计划。如果您只想显示来自A
的列(而没有来自B
的列),那么您可以尝试使用EXISTS
而不是外部连接到表,尽管通常查询规划器足够聪明,可以在后面为您执行此操作场景。你能指出实际的底层数据库是 SQL Server 还是 mysql?
【参考方案1】:
这个查询可能更快地返回正确的结果,或者它可能返回不正确的结果而不提高速度
这都是基于 SQL Server 知识,但我假设 InnoDB 具有相同的特征。
SELECT Name
FROM A
WHERE A.isPair = 'T'
AND NOT EXISTS (
SELECT 1 FROM B
WHERE A.Name = B.Name2
AND B.status = 'valid'
)
我希望我正确地重新排列了布尔逻辑。
在您在 A 中搜索在 B 中不匹配或匹配状态为 有效
的记录之前新查询返回来自 A 的记录,它在 B 中找不到状态 = 有效的匹配项。希望这是同样的事情。
我在这里使用了两个数据库概念:
当使用 EXISTS 时,它可以只查看表记录是否存在,它不必加入表并从中检索值.....尽管大多数查询计划程序会自动执行此操作,所以这是一个远射
1234563它只能搜索特定值的索引。所以我把它改成了=
,也是因为它支持NOT EXISTS
逻辑
同样,我对 InnoDB 了解不多,但我敢肯定,如果它没有这些限制,这些技巧早就被 Oracle 和 Microsoft 复制了。
比较查询计划会让您了解这种重写是否有任何不同。此外,比较现有 INNER 和 OUTER 查询版本之间的查询计划可能会有所帮助。
【讨论】:
我不止一次听说过,由于某些原因,在 MySQL 中使用LEFT JOIN ... WHERE ... IS NULL
而不是使用 NOT EXISTS
实现反连接会更有效地工作。因此,尝试另一种选择可能是有意义的:... LEFT JOIN B ON
A.Name = B.Name2 AND B.status = 'valid' WHERE B.Name2 IS NULL`。我不是 MySQL 专家,所以只是评论(但如果您认为值得,请随时将此版本添加到您的答案中)。以上是关于左连接似乎极大地阻碍了 SQL 查询性能的主要内容,如果未能解决你的问题,请参考以下文章