因此,algebrizer 中的简化应该将一些子查询转换为内连接或外连接。例如,我尝试了这个
DBCC TRACEON(3604)
USE ContosoRetailDW
BEGIN TRAN
SELECT ProductKey
FROM DimProduct
WHERE ProductKey IN (SELECT ProductKey
FROM FactSales
WHERE SALESKEY <2)
OPTION(RECOMPILE,QUERYTRACEON 8605)
COMMIT TRAN
输出是
*** Converted Tree: ***
LogOp_Project QCOL: [ContosoRetailDW].[dbo].[DimProduct].ProductKey
LogOp_Select
LogOp_Get TBL: DimProduct DimProduct TableID=117575457 TableReferenceID=0 IsRow: COL: IsBaseRow1000
ScaOp_SomeComp 2
ScaOp_Identifier QCOL: [ContosoRetailDW].[dbo].[DimProduct].ProductKey
LogOp_Project
LogOp_Select
LogOp_Get TBL: FactSales FactSales TableID=1602104748 TableReferenceID=0 IsRow: COL: IsBaseRow1002
ScaOp_Comp x_cmpLt
ScaOp_Identifier QCOL: [ContosoRetailDW].[dbo].[FactSales].SalesKey
ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=2)
AncOp_PrjList
AncOp_PrjList
*******************
如果我把它改写成
BEGIN TRAN;
SELECT DISTINCT dp.ProductKey
FROM DimProduct dp
JOIN FactSales fs ON dp.ProductKey = fs.ProductKey
WHERE fs.SalesKey < 2
OPTION (RECOMPILE, QUERYTRACEON 8605);
COMMIT TRAN;
我明白了
*** Converted Tree: ***
LogOp_GbAgg OUT(QCOL: [dp].ProductKey,) BY(QCOL: [dp].ProductKey,)
LogOp_Project
LogOp_Project QCOL: [dp].ProductKey
LogOp_Select
**LogOp_Join**
LogOp_Get TBL: DimProduct(alias TBL: dp) DimProduct TableID=117575457 TableReferenceID=0 IsRow: COL: IsBaseRow1000
LogOp_Get TBL: FactSales(alias TBL: fs) FactSales TableID=1602104748 TableReferenceID=0 IsRow: COL: IsBaseRow1001
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [dp].ProductKey
ScaOp_Identifier QCOL: [fs].ProductKey
ScaOp_Comp x_cmpLt
ScaOp_Identifier QCOL: [fs].SalesKey
ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=2)
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
*******************
所以,问题是:如何在第一个查询中获取LogOp_Join ?
我尝试创建一个包含 5000 万行的类似表,但仍然没有成功。导致这种情况发生的条件是什么?
您的第一个查询包含一个子查询,该子查询被取消嵌套(
RemoveSubqInSel
)以应用半连接,然后被转换(ApplyHandler
)为半连接。稍后基于成本的转换考虑将其转换为连接(通过引入分组/区分操作)。
第二个查询完全不同,因为它以逻辑连接开始。
代数器中不会进行简化。有许多早期转换阶段,并且可选地进行基于成本的探索。
您展示的输出仅仅是一个复杂过程的早期阶段。