泰迦奥特曼 发表于 2023-9-13 14:26:10

SQL Server中INNER JOIN与LEFT JOIN的性能

我创建了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 JOIN或RIGHTJOIN)所有的工作都必须完成INNERJOIN以及结果null额外的扩展工作。仅仅因为结果集的大小,我们也希望回到更多的行,从而进一步增加了总执行时间。
(而且即使LEFT JOIN 是    在更快的 特定    在这种情况下,由于一些难以想象的因素,它并不等同于功能INNERJOIN,所以你不能简单地改变所有其他例子!)
你的性能问题很可能位于其他地方,比如没有正确的索引候选人键或外部键。有很多地方可以添加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 t1INNER JOIN #Test2 t2ON t2.Name = t1.NameSELECT *FROM #Test1 t1LEFT JOIN #Test2 t2ON t2.Name = t1.NameDROP TABLE #Test1DROP TABLE #Test2如果操作此命令并查看执行计划,则会发现INNER JOIN查询确实比花费更多LEFT JOIN,这是因为它满足了上述两个条件。SQL
Server希望散列匹配INNER JOIN,但是嵌套循环LEFT JOIN。前者 通常    快多了,但是因为行数很小 并且
没有索引可用,因此哈希运算被证明是查询中最昂贵的部分。
通过使用你最喜欢的编程语言来编写程序,你可以在五个元素的列表与五个元素的哈希表)上找到大量的搜索,你可以看到相同的效果。由于大小,散列表的版本实际上更慢。但由于哈希表的速度较慢,将其添加到50个元素或5000个元素中O(N)对O(1)。
但将此查询改为ID列而不是列Name,你会看到一个完全不同的故事。在这种情况下,它是两个查询嵌套循环,但INNERJOIN版本可以取代聚簇索引扫描和寻求-这意味着这只是 一个数量级    速度更快。
因此,结论或多或少是我上面提到的。这几乎肯定是一个索引或索引覆盖问题,可能与一个或多个非常小的表相结合。在这种情况下,SQL
Server有时 可能    为而INNER JOIN不要选择更糟糕的执行计划LEFT JOIN。
页: [1]
查看完整版本: SQL Server中INNER JOIN与LEFT JOIN的性能