Pau*_*mes 9 sql-server optimization database-internals except
下面的 EXCEPT 查询生成一个带有看似无目的投影的逻辑计划。INTERSECT 也会发生这种情况。
投影的目的是什么?例如,是否有不同的 EXCEPT 查询,其中外投影会指定某些内容?
询问:
use AdventureWorks2017
select p.ProductId
from Production.Product as p
except
select pinv.ProductID
from Production.ProductInventory as pinv
option (recompile, querytraceon 8605, querytraceon 3604)
Run Code Online (Sandbox Code Playgroud)
转换树:
LogOp_Select
LogOp_GbAgg OUT(QCOL: [p].ProductID,) BY(QCOL: [p].ProductID,)
LogOp_Project -- << ?? PASSIVE PROJECTION ??
LogOp_Project
LogOp_Get TBL: Production.Product(alias TBL: p) Production.Product TableID=482100758 TableReferenceID=0 IsRow: COL: IsBaseRow1000
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
ScaOp_Exists
LogOp_Select
LogOp_Project
LogOp_Get TBL: Production.ProductInventory(alias TBL: pinv) Production.ProductInventory TableID=914102297 TableReferenceID=0 IsRow: COL: IsBaseRow1001
AncOp_PrjList
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [p].ProductID
ScaOp_Identifier QCOL: [pinv].ProductID
Run Code Online (Sandbox Code Playgroud)
Con*_*SFT 14
我们在查询优化器内部做的各种事情并没有我们可以在外部解释的真正原因。您在优化器中看到的项目最终会在优化器的末尾被重写以“扁平化”表达式。因此,优化器在搜索中有一些东西是代码实现方式的一部分,这些东西可能会引入额外的项目,这些项目实际上在功能上没有做任何事情,但允许我们将在优化器的一部分中创建一个子树的地方拼接在一起但后来在原本不打算使用的地方使用。有一些物理实现细节会导致这种情况发生。就计划质量而言,它们对用户都不重要(几乎在任何情况下 - 我们已经努力使这些在搜索中无关紧要)。
所以,我只是挥挥手说“你不需要看他的身份证明。他可以做他的事。继续前进”;)。
Pau*_*ite 11
我对此没有一个完全令人满意的答案,但DISTINCT被转换为一个项目加上分组聚合。
二者EXCEPT并INTERSECT配有一个隐含的DISTINCT在第一表表达式。正是这DISTINCT一点导致树中的“空白”项目。它是无害的。
如果您将 a 写DISTINCT为等效的GROUP BY,您将看不到空白项目。项目出现在聚合之后:
SELECT DISTINCT P.ProductID
FROM Production.Product AS P
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
Run Code Online (Sandbox Code Playgroud)
SELECT DISTINCT P.ProductID
FROM Production.Product AS P
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
Run Code Online (Sandbox Code Playgroud)
SELECT P.ProductID
FROM Production.Product AS P
GROUP BY p.ProductID
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
Run Code Online (Sandbox Code Playgroud)
LogOp_GbAgg OUT(QCOL: [P].ProductID,) BY(QCOL: [P].ProductID,)
LogOp_Project
LogOp_Project QCOL: [P].ProductID
LogOp_Get TBL: Production.Product(alias TBL: P)
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
Run Code Online (Sandbox Code Playgroud)