INNER JOIN与LEFT JOIN在SQL Server的性能

我创建了INNER JOIN 9桌,反正需要很长的(超过五分钟)。所以,我的民歌改变INNER JOIN来LEFT JOIN LEFT JOIN的性能较好,在首次尽管我所知道的。之后我变了,查询的速度显著提高。 我想知道为什么LEFT JOIN的速度比INNER JOIN? 我的样子如下: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


本文地址 :CodeGo.net/150174/ 
------------------------------------------------------------------------------------------------------------------------- 
1. 一LEFT JOIN比绝对不是更快INNER JOIN。事实上,它的速度较慢,根据定义,一个外部联接(LEFT JOINRIGHT JOIN)所要做的所有工作INNER JOIN空扩展结果的额外工作。它也将有望重回更多的行,进一步增加了总的执行简单地归结到结果集的规模越大。 (而且,即使一LEFT JOIN是在特定的情况下更快的原因有多种难想象合流,它不是在函数上等同于INNER JOINCodeGo.net,所以你不能简单地去替换一个与其他的所有实例!) 最有可能的性能问题在其他地方,如没有一个候选键或适当的索引外键。 9表格是相当多的,能够加入这样的放缓可以从字面上几乎任何地方。如果您发布您的模式,我们也许能够提供更多的细节。 编辑: 进一步反映在此,我能想到的下一个plotLEFT 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 JOINLEFT JOIN 
2. 有可能导致外部联接比内部更快地联接尚未又一个重要的场景。 外连接,优化一直是free的,从执行计划下降外连接表,如果连接列是外部表中的PK,并没有列是从外部表中选择。例如SELECT A.* FROM A LEFT OUTER JOIN B ON A.KEY=B.KEY和B.KEY是PK的B.两个甲骨文(我相信我释放10)和SQL Server(2008 R2)从执行计划trimB表。 的未必是真实的内部联接:SELECT A.* FROM A INNER JOIN B ON A.KEY=B.KEY可能会或可能不会要求乙方在执行计划根据什么constraints存在。 如果A.KEY是空的外键引用B.KEY,那么优化器不能从它必须确认A B行存在,每一个行的计划落乙。 如果A.KEY是一个强制性的外键引用B.KEY,那么优化器可以自由地从该计划的constraints保证该行的存在降乙。但是,仅仅优化器可以从该计划删除表,没有按'会的。 SQL Server 2008的R2不会从该计划跌落乙级。甲骨文10没有从计划跌落乙级。这是很容易看到的外部如何连接将在性能在这种情况下,内部联接的SQL Server上。 这是一个简单的例子,而不是实际的一个独立的查询。为什么要加入到一个表,如果你不需要? 而设计的观点时,这可能是一个非常重要的设计考虑。经常是“做一切”的观点是建立联接一切可能需要涉及到中央台。 (尤其是如果有做adhoc查询不理解关系模型)视图可以包括来自多个表中的所有相应和列。但是从视图中的表的子集的可能只访问列。如果表的连接与外连接,那么优化器可以(不)从计划落了人需要的表。 关键是要确保该外部联接给出了正确的结果。正如Aaronaught所说的-你不能一味替代OUTER JOIN的INNER JOIN和expect的结果。但是,出于性能原因的观点是何时能。 最后一个注意-我没有测试过对性能的影响,鉴于上述情况,但在理论上似乎你应该能够安全地替换INNER JOIN与OUTER JOIN,如果您还添加了状态<FOREIGN_KEY> IS NOT空的地方 
3. 我所知道的几起案件,其中左连接已经比内连接速度更快。 其根本原因,我能想到的是这样的: 如果你有两个表与您携手与索引(两个表)的列。 内部联接将产生的结果不管你循环遍历上表中的一个,并配以索引表中的两个索引中的条目,如果你会做相反的:在循环中的条目索引表中的两个,并配以指数表中的一个。 问题是,当你有旧的统计数据,我查询优化索引的统计信息来找到表与至少匹配的条目(根据你的其他条件)。 如果你有两个表中的每个100万,在表中的一个有10行匹配,并在表中的两个有100000行匹配。最好的办法是做一个索引扫描的表之一,并在表中两个匹配10。相反将是一个索引扫描的遍历100000行和尝试匹配100000,只有10所以,如果统计不正确的优化器可能会选择错误的表和索引遍历。 如果优化器选择最佳的左连接在它被写入命令将执行比内连接好。 但是,优化器也可以优化左连接子优化的左半联接。为了使选择你想你FORCE ORDER提示之一。 
4. 试试这两个查询(一个与内部和左连接)与OPTION (FORCE ORDER)在结束后的结果。OPTION (FORCE ORDER)是一个查询提示强制优化器与您在查询中提供的连接顺序生成执行计划。 如果INNER JOIN开始执行一样快LEFT JOIN,它是 在一个完全由INNER JOINs时,连接顺序并不重要。这给自由查询优化下令其认为合适的联接,所以该问题可能依靠优化上。 同LEFT JOIN,这是不是这样的改变连接顺序将改变查询的结果。引擎必须按照您提供的查询,这可能比优化的更好的连接顺序。 不知道这个回答你的问题,但我曾经在这特色的查询进行计算的一个项目,其中最多的优化。我们有情况下,一个FORCE ORDER将减少一个查询的执行从5分钟至10秒。 
5. 您的性能问题更可能是连接你正在做的和你要加入的列是否具有索引或数量不限的。 你可以很容易地做9全表最坏的情况下会扫描每个加盟。 
6. 已经做了一些左外部和内部连接和一直没能找到一个consisten之间的差异。有许多变数。我工作的一个报告数据库中有很多的表有大量的字段,在(providers版本和当地工作线程)的许多变化。这是不可能创建所有覆盖索引等多种查询的需要和处理历史数据。已经看到的内层查询kill服务器性能两个大(百万到上千万行)表是内部加入了两个拉大了许多领域,并没有覆盖索引的存在。 但最大的问题,似乎并没有在上面appeaer。也许你的数据库是精心设计与触发器和精心设计的交易处理,以确保良好的数据。矿经常有,他们没有预计NULL值。是的表定义可以执行无空值,但不是在我的选项 所以,问题是...你设计你的查询只对速度,事务处理更高优先级运行一分钟的代码。或者你去的准确性,一个左外连接将提供。该内部连接必须找到双方的,所以一个意想不到的空不仅会从两个表中删除数据,但有可能整个行和它发生这么好听,不 你可以非常快地得到90%所需要的数据,并没有发现内部连接有默默的内部连接可以更快,但我不相信任何人做这样的假设,除非他们已审阅的执行计划。速度是重要的,但是精确度更重要。

原文地址:https://www.cnblogs.com/littlewrong/p/5267192.html