当前位置: 首页 > 面试题库 >

SQL Server中INNER JOIN与LEFT JOIN的性能

狄侯林
2023-03-14
问题内容

我创建了在9个表上使用INNER JOIN的SQL命令,无论如何,此命令将花费很长时间(超过五分钟)。所以我的同事建议我将INNER JOIN更改为LEFT
JOIN,因为尽管我知道,但LEFT JOIN的性能更好。更改后,查询速度得到了显着提高。

我想知道为什么LEFT JOIN比INNER JOIN快?

我的SQL命令看起来象下面这样: SELECT * FROM A INNER JOIN B ON ... INNER JOIN C ON ... INNER JOIN D

更新: 这是我的架构的简要介绍。

FROM sidisaleshdrmly a -- NOT HAVE PK AND FK
    INNER JOIN sidisalesdetmly b -- THIS TABLE ALSO HAVE NO PK AND FK
        ON a.CompanyCd = b.CompanyCd 
           AND a.SPRNo = b.SPRNo 
           AND a.SuffixNo = b.SuffixNo 
           AND a.dnno = b.dnno
    INNER JOIN exFSlipDet h -- PK = CompanyCd, FSlipNo, FSlipSuffix, FSlipLine
        ON a.CompanyCd = h.CompanyCd
           AND a.sprno = h.AcctSPRNo
    INNER JOIN exFSlipHdr c -- PK = CompanyCd, FSlipNo, FSlipSuffix
        ON c.CompanyCd = h.CompanyCd
           AND c.FSlipNo = h.FSlipNo 
           AND c.FSlipSuffix = h.FSlipSuffix 
    INNER JOIN coMappingExpParty d -- NO PK AND FK
        ON c.CompanyCd = d.CompanyCd
           AND c.CountryCd = d.CountryCd 
    INNER JOIN coProduct e -- PK = CompanyCd, ProductSalesCd
        ON b.CompanyCd = e.CompanyCd
           AND b.ProductSalesCd = e.ProductSalesCd 
    LEFT JOIN coUOM i -- PK = UOMId
        ON h.UOMId = i.UOMId 
    INNER JOIN coProductOldInformation j -- PK = CompanyCd, BFStatus, SpecCd
        ON a.CompanyCd = j.CompanyCd
            AND b.BFStatus = j.BFStatus
            AND b.ProductSalesCd = j.ProductSalesCd
    INNER JOIN coProductGroup1 g1 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup1Cd
        ON e.ProductGroup1Cd  = g1.ProductGroup1Cd
    INNER JOIN coProductGroup2 g2 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup2Cd
        ON e.ProductGroup1Cd  = g2.ProductGroup1Cd

问题答案:

ALEFT JOIN绝对不会比A快INNER JOIN。实际上,它比较慢。根据定义,外部联接(LEFT JOINRIGHT JOIN)必须完成所有工作INNER JOIN以及对结果进行null扩展的额外工作。仅仅由于结果集的大小,也期望返回更多的行,从而进一步增加了总的执行时间。

(而且即使LEFT JOIN 在更快的 特定 情况下,由于一些难以想象的因素汇合,它不是功能上等同于INNER JOIN,所以你不能简单地去更换一个与其他的所有实例!)

您的性能问题很可能位于其他地方,例如没有正确索引候选键或外键。9个表有很多要加入的地方,因此减速几乎可以在任何地方进行。如果您发布架构,我们也许可以提供更多详细信息。

编辑:

进一步思考这一点,我可以想到一种情况,在这种情况下,aLEFT JOIN可能比快INNER JOIN,而在这种情况下:

  • 一些表是 非常 小的(比如说,在10行);
  • 这些表没有足够的索引来覆盖查询。

考虑以下示例

CREATE TABLE #Test1
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test1 (ID, Name) VALUES (1, 'One')
INSERT #Test1 (ID, Name) VALUES (2, 'Two')
INSERT #Test1 (ID, Name) VALUES (3, 'Three')
INSERT #Test1 (ID, Name) VALUES (4, 'Four')
INSERT #Test1 (ID, Name) VALUES (5, 'Five')

CREATE TABLE #Test2
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test2 (ID, Name) VALUES (1, 'One')
INSERT #Test2 (ID, Name) VALUES (2, 'Two')
INSERT #Test2 (ID, Name) VALUES (3, 'Three')
INSERT #Test2 (ID, Name) VALUES (4, 'Four')
INSERT #Test2 (ID, Name) VALUES (5, 'Five')

SELECT *
FROM #Test1 t1
INNER JOIN #Test2 t2
ON t2.Name = t1.Name

SELECT *
FROM #Test1 t1
LEFT JOIN #Test2 t2
ON t2.Name = t1.Name

DROP TABLE #Test1
DROP TABLE #Test2

如果运行此命令并查看执行计划,则会发现INNER JOIN查询确实比花费更多LEFT JOIN,因为它满足了上述两个条件。这是因为SQL
Server希望对进行散列匹配INNER JOIN,但对进行嵌套循环LEFT JOIN。前者 通常 要快得多,但是由于行数非常小 并且
没有索引可使用,因此哈希运算被证明是查询中最昂贵的部分。

通过使用自己喜欢的编程语言编写程序,在具有5个元素的列表(与具有5个元素的哈希表)上执行大量查找,您可以看到相同的效果。由于大小,散列表的版本实际上要慢一些。但是将其增加到50个元素或5000个元素,并且列表版本的速度变慢,因为哈希表的O(N)对O(1)。

但是将此查询更改为ID列而不是列Name,您将看到一个截然不同的故事。在这种情况下,它为两个查询嵌套循环,但INNER JOIN版本能够取代聚簇索引扫描的一个与寻求-这意味着这简直就 一个数量级 有大量行的速度更快。

因此,结论或多或少是我上面提到的几段内容。这几乎可以肯定是一个索引或索引覆盖问题,可能与一个或多个非常小的表结合在一起。在这些情况下,SQL
Server有时 可能 为而INNER JOIN不是选择更糟糕的执行计划LEFT JOIN



 类似资料:
  • 问题内容: 我想以以下方式实现sql查询: 我该如何使用或上面提到的方法来做到这一点? 问题答案: 是一个方法从查询类。 您可以尝试这样的事情。

  • 我有一个2.1.4版本的项目,带有spring boot数据。 该项目具有以下关系实体:ApplicationEntity ApplicationTranslateEntity LanguageEntity它在数据库中有一个区域设置关系表(ManyToMany),该表中有一个用于不同语言的文本的额外表(ApplicationTranslateEntity)。 org.hibernate.Query

  • 问题内容: 我正在尝试在SQLServer中聚合“ STRING”字段。我想找到与Oracle中相同的函数LISTAGG。 您知道如何执行相同的功能或其他方法吗? 例如, 我希望这个查询的结果是 问题答案: 从SQL Server 2017开始,该功能可用,从而大大简化了逻辑: 在SQL Server中,您可以用来获取结果:

  • 我阅读了kstream.leftjoin,但没有找到确切的区别。

  • 本文向大家介绍SQLServer地址搜索性能优化,包括了SQLServer地址搜索性能优化的使用技巧和注意事项,需要的朋友参考一下 这是一个很久以前的例子,现在在整理资料时无意发现,就拿出来再改写分享。 1.需求  1.1 基本需求: 根据输入的地址关键字,搜索出完整的地址路径,耗时要控制在几十毫秒内。  1.2 数据库地址表结构和数据:  表TBAddress    表数据    1.3 例子:

  • 问题内容: 这个问题已经在这里有了答案 : SQL中的TRUNCATE和DELETE有什么区别 (32个答案) TRUNCATE vs DELETE FROM的利弊 (11个答案) 6年前关闭。 关于mysql / sqlserver,我的脑海里发生了一件事,即 删除/截断 哪个更好更快? 在哪里使用删除? 在哪里使用截断? 问题答案: 删除 DELETE是DML命令。 使用行锁执行DELETE语

  • node-sqlserver 是微软官方发布的 SQL Server 的 Node.js 的驱动程序。可允许 Windows 上运行的 Node.js 程序访问 SQL Server 和 Windows Azure SQL 数据库。 该项目托管在 Github 上。

  • sqlserver manager 是一个多功能sqlserver图形管理界面,支持自定义导入导出,自动扫描服务器,数据库。