wom*_*omp 4 sql t-sql sql-server sql-server-2005 subquery
我有一个大型查询,其中一个简单的子查询优化将其从 8 分钟缩短到 20 秒。我不确定我是否理解为什么优化会产生如此剧烈的影响。
本质上,这是问题部分:
SELECT (bunch of stuff)
FROM
a LEFT OUTER JOIN b ON a.ID = b.a
LEFT OUTER JOIN c ON b.ID = c.b
...
...
INNER JOIN veryLargeTable
ON a.ID = veryLargeTable.a
AND veryLargeTable.PetID =
(SELECT id from Pets WHERE Pets.Name = 'Something') /* BAD! */
...
...
Run Code Online (Sandbox Code Playgroud)
总共有 16 个连接表。如果我用veryLargeTable包含 petID 的预填充变量替换连接的第二个谓词(而不是使用子查询),则整个查询会显着加快:
AND veryLargeTable.PetID = @petID /* Awesome! */
Run Code Online (Sandbox Code Playgroud)
显然,(SELECT id from Pets WHERE Name = 'Something')正在为每一行执行。有两件事我不完全理解:
据我所知,这是一个不相关的子查询。Pets 表根本不是外部查询的一部分。不相关的子查询不是独立评估(并因此优化)吗?为什么这里不是这种情况?
执行计划截然不同。在失败的情况下(上图),整个子树处理大约 950k 行。在获胜的情况下(使用变量而不是子查询),估计只有大约 125k 行。这是怎么回事?如果存在该子查询,为什么会涉及更多行?Pets.Name 列肯定有唯一的数据(但据我所知没有唯一的约束)。
请注意,将谓词移动到 WHERE 子句在任何一种情况下都不会影响查询,正如我所期望的,因为它是一个 INNER JOIN。
见解赞赏!
根据我的经验,查询越复杂,SQL 优化器创建灵巧计划的能力就越低。这里你有 16 个连接,一些或大部分是外连接,你至少有一个子查询……加入足够多的索引、基数、视图、外应用,谁知道还有什么,没有人,甚至微软也不知道工程师*,可以找出将统一和定期生成最佳计划的例程。
你所描述的,我已经经历过无数次——在一个凌乱的查询中改变一件简单的事情,一切都快了一个数量级(或者,咬牙切齿,更慢)。我没有办法确定复杂何时太复杂,它更像是一种感觉而不是其他任何东西。我的一般经验法则是,如果它看起来太长或太复杂,请尽可能简化 - 例如您预先选择的单个嵌套值,或者打破查询的一部分,而不是总是使用小结果集快速运行,并首先运行它并将结果存储在临时表中。
( * 请注意,这是温和的讽刺)
| 归档时间: |
|
| 查看次数: |
1551 次 |
| 最近记录: |