内部联接是不是存在任何性能问题?

Posted

技术标签:

【中文标题】内部联接是不是存在任何性能问题?【英文标题】:Is there any performance issue with Inner Join?内部联接是否存在任何性能问题? 【发布时间】:2009-07-21 06:35:14 【问题描述】:

目前我在我的 sp 中使用了很多内部连接(大约 7 个),它对 sp 性能有什么影响吗?左外连接是否比内连接提供更好的性能。

如果我要加入两个表 a 和 b,其中包含列 id 和 id1,那么还有一件事,两者 r 都不能为空。我想在这里我可以在这些列被索引时进行内部连接。

【问题讨论】:

您对用于连接条件的列(以及用于其他条件的任何列,例如在 where 子句中)是否有索引?它可以真的提供帮助。一般来说,我听说 inner 的性能比 left 好——但是应该使用什么取决于你想要得到什么^^ 【参考方案1】:

外连接比内连接更昂贵。我将要说的话会引起很多人的争议。如果你对数据库进行了正确的调整,如果你没有做任何愚蠢的事情,并且如果你使用的是专业的 RDBMS,那么 7 个内部连接应该不是问题。

我所说的数据库调优是什么意思?数据库调整有很多内容,但最明显的检查是确保您始终连接已索引的列。

我说的傻是什么意思?不要在连接条件中使用 OR 运算符。尝试将连接保持在单个比较上,例如一个表中的外键等于另一个表中的主键。尝试将所有关键字段键入为整数。

如果您确实遇到性能问题,请务必研究有问题的查询的执行计划。例如,在连接非常大的表时可能会遇到问题,大到甚至索引扫描都太慢了。您可能必须进行非规范化并提供额外的过滤以减少扫描时间。不要试图预测这一点。非规范化最好在遇到实际性能情况后才进行。

【讨论】:

有争议的部分又在哪里?加盟数量?我认为它只取决于正在加入哪些表。此外,关于OR 子句的好建议。它们看似昂贵,尤其是在 SQL Server 中。 我过去曾与开发人员合作过,他们认为出于性能原因不应超过三个连接。早在 1980 年代我就会同意这一点,但今天不会。【参考方案2】:

JOIN 用于特定目的而非性能。

LEFT OUTER JOIN 用于包含右侧表中没有匹配记录的记录。 INNER JOIN 根据某些条件在两个表中选择匹配的记录。

【讨论】:

这个关于 LEFT OUTER JOIN 的小消息对我很有帮助。从 INNER JOIN 切换到 OUTER JOIN 将我的查询从 16 秒缩短到 50 毫秒。我没有搜索任何连接表的列,因此可以在事后连接它。【参考方案3】:

左连接与内连接给出不同的结果,因此不应用作替代。很可能它是您需要的索引。虽然在定义主键时会自动创建索引,但在定义外键时不会创建索引。因此,如果您还没有索引连接中的所有这些外键,则需要索引。

还要检查您的执行计划,看看问题出在哪里。

有关优化查询性能的方法的更具体建议,您需要向我们展示。

【讨论】:

【参考方案4】:

连接通常很昂贵的原因是连接可能会导致一些元组大于任一表的大小。

但是,有时一个表中的连接属性在功能上确定了另一个表中的唯一元组。在这种情况下,连接可能非常便宜(但您需要对这些属性进行索引)。

这将是一个便宜的操作,不管你做了多少连接——它更多的是数据和数据依赖的问题。

由于您要加入 2 个键,看起来两个表都使用了相同的键,因此无论您使用哪种联接,这都应该是一个便宜的操作。

【讨论】:

【参考方案5】:

首先,这两个是为了服务于不同的目的。因此,比较可能并非在所有情况下都有效。

您可以在此处阅读更多内容。

Performance tuning SQL Server joins

【讨论】:

【参考方案6】:

要跟进Glenn said 的内容,如果您要加入“愚蠢的东西”,那么提前将其提取到临时表中也可能会有所帮助。

在我过去工作过的一个数据库中,连接是在一个部分键上的(表有复合键,即一个包含许多列的主键),并且在 where 子句中进行了额外的过滤。 where 子句中的过滤将要查看的行集从连接一侧的数十亿降低到数千。加入数千行的表比加入数十亿行要容易得多。我记得查询时间从 20 分钟缩短到 7 秒。

另外请注意,我们在其中也有子查询和 UDF(用户定义的函数) - 这可能会增加愚蠢性。

【讨论】:

以上是关于内部联接是不是存在任何性能问题?的主要内容,如果未能解决你的问题,请参考以下文章

外部联接中的内部联接导致性能不足,有啥不同的方法?

两个索引上的内部联接的 Big-Oh 性能

MySQL:内部联接与 Where [重复]

SQL Server 2005 - 内部联接的顺序

在您的 html 中包含大量脚本标签是不是存在任何性能问题?

内部联接与内部联接(SELECT . FROM)