então a simplificação no algebrizador deve converter algumas das subconsultas em junções internas ou externas. por exemplo, eu tentei isso
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
a saída foi
*** 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
*******************
se eu reescrever assim
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;
Eu entendo
*** 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
*******************
Então, a questão é: Como posso obter o LogOp_Join na primeira consulta?
Tentei criar uma tabela similar com 50 milhões de linhas, mas ainda não aconteceu. Quais são as condições que fazem isso acontecer?
Sua primeira consulta contém uma subconsulta, que é desaninhada (
RemoveSubqInSel
) para uma semi junção de aplicação e depois transformada (ApplyHandler
) para uma semi junção.Uma transformação posterior baseada em custos considera converter isso em uma junção (por meio da introdução de uma operação de agrupamento/distinção).
A segunda consulta é bem diferente, pois começa com uma junção lógica.
A simplificação não ocorre no algebrizador. Há muitos estágios de transformação inicial e, opcionalmente , exploração baseada em custo.
O resultado que você mostrou estava apenas em um estágio inicial de um processo complexo.