左连接似乎极大地阻碍了 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 查询性能的主要内容,如果未能解决你的问题,请参考以下文章

对两个 MySQL 查询执行左外连接?

SQL Db2 中的左连接而不是不存在

SQL 查询左连接问题

SQL查询中左连接之后的所有连接是不是也必须是左连接?为啥或者为啥不?

左连接混淆的 Sql 查询[关闭]

如何将在左连接中具有连接的 sql 转换为查询构建器?