回答

收藏

SQL Server中INNER JOIN与LEFT JOIN的性能

技术问答 技术问答 41 人阅读 | 0 人回复 | 2023-09-13

我创建了9个表的使用INNER JOIN的SQL无论如何,这个命令将需要很长时间(超过五分钟)。所以我的同事建议我INNER JOIN更改为LEFT& C5 M2 u/ n. O% n
JOIN,虽然我知道,但是LEFT JOIN性能更好。更改后,查询速度显著提高。
2 n' H8 T1 }8 b" I) R$ j  H# k" t我想知道为什么LEFT JOIN比INNER JOIN快?
; R/ j8 J# ]$ [  M  t0 `5 I' K我的SQL命令看起来象下面这样: SELECT * FROM A INNER JOIN B ON ... INNER JOIN C ON ...INNER JOIN D等
4 e# |# b/ O) P0 H; h; i更新:    这是我对结构的简要介绍。
. ]( J! j- _5 S2 o% MFROM 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                " i4 o# i% {( w8 p
    解决方案:                                                               
, H2 p9 s- a6 C4 ^                                                                ALEFT JOIN绝对不会比A快INNER JOIN。事实上,它相对较慢。根据定义,外部连接(LEFT JOIN或RIGHTJOIN)所有的工作都必须完成INNERJOIN以及结果null额外的扩展工作。仅仅因为结果集的大小,我们也希望回到更多的行,从而进一步增加了总执行时间。2 Y9 _3 K2 r6 M! z/ L$ s
(而且即使LEFT JOIN 是    在更快的 特定    在这种情况下,由于一些难以想象的因素,它并不等同于功能INNERJOIN,所以你不能简单地改变所有其他例子!)4 q% V8 O: t. z8 ^4 _3 X& a
你的性能问题很可能位于其他地方,比如没有正确的索引候选人键或外部键。有很多地方可以添加9个表,所以减速几乎可以在任何地方进行。如果您发布架构,我们可以提供更多详细信息。
$ f3 W* W* Z# l, m2 Y' U5 y编辑:, U6 _- U) n! y9 v5 B' c
进一步思考这一点,我可以想到一种情况,aLEFT JOIN可能比快INNER JOIN,在这种情况下:# |, [. M  E5 v8 e0 k# E/ V! R
一些表是 非常    小(比如10行);
' s. K% G3 p: t0 ~+ ~- {1 ~没有足够的索引来覆盖查询。
考虑以下示例:' F/ K% l4 J4 Q0 q
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,这是因为它满足了上述两个条件。SQL1 `0 V9 V8 o8 a# {( p. A
Server希望散列匹配INNER JOIN,但是嵌套循环LEFT JOIN。前者 通常    快多了,但是因为行数很小 并且9 p$ z$ |8 I: e4 h" a8 j0 R
没有索引可用,因此哈希运算被证明是查询中最昂贵的部分。
6 P# |$ X, o, l  G; m. s通过使用你最喜欢的编程语言来编写程序,你可以在五个元素的列表与五个元素的哈希表)上找到大量的搜索,你可以看到相同的效果。由于大小,散列表的版本实际上更慢。但由于哈希表的速度较慢,将其添加到50个元素或5000个元素中O(N)对O(1)。% e. g6 j/ f5 |
但将此查询改为ID列而不是列Name,你会看到一个完全不同的故事。在这种情况下,它是两个查询嵌套循环,但INNERJOIN版本可以取代聚簇索引扫描和寻求-这意味着这只是 一个数量级    速度更快。3 j: E. a. n9 I& V
因此,结论或多或少是我上面提到的。这几乎肯定是一个索引或索引覆盖问题,可能与一个或多个非常小的表相结合。在这种情况下,SQL
) o" K4 Q& Q  `Server有时 可能    为而INNER JOIN不要选择更糟糕的执行计划LEFT JOIN。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则