在下面的例子中添加DISTINCT
对查询运行时间有影响吗?
有时将它用作提示是否明智?
SELECT *
FROM A
WHERE A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B)
当想知道这样的事情时,您应该比较查询的执行计划。
您的查询执行计划的形状当然会有所不同,具体取决于您的表中有多少行以及定义了哪些索引。
显示性能没有差异的一种情况是 中的行A
数比 中的行数多得多B
。然后优化器将选择B
作为嵌套循环连接中的驱动表A
。为了得到正确的结果,它必须B
在两个查询中对表使用流聚合,以仅从中获取不同的行B
。所以在这种情况下,distinct 关键字对性能没有影响。
其他两个要测试的明显案例的执行计划,B 中的行多于 A 且表中的行数相等,也显示了完全相同的查询执行计划。
更新
在查询优化发生之前,查询会经历一个简化阶段。您可以使用跟踪标志 8606 查看逻辑树的外观。
查询的输入树明显不同,但在简化后它们是相同的。
参考:更多未记录的查询优化器跟踪标志和查询优化器深入研究 - 第 2 部分
使用 distinct 进行查询的输入树和简化树:
*** Input Tree: ***
LogOp_Project QCOL: [xx].[dbo].[A].SomeColumn
LogOp_Select
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
ScaOp_SomeComp 2
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
LogOp_GbAgg OUT(QCOL: [xx].[dbo].[B].SomeColumn,) BY(QCOL: [xx].[dbo].[B].SomeColumn,)
LogOp_Project
LogOp_Project
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
*******************
*** Simplified Tree: ***
LogOp_LeftSemiJoin
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
ScaOp_Identifier QCOL: [xx].[dbo].[B].SomeColumn
*******************
不使用 distinct的查询的输入树和简化树:
*** Input Tree: ***
LogOp_Project QCOL: [xx].[dbo].[A].SomeColumn
LogOp_Select
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
ScaOp_SomeComp 2
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
LogOp_Project
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
AncOp_PrjList
AncOp_PrjList
*******************
*** Simplified Tree: ***
LogOp_LeftSemiJoin
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
ScaOp_Identifier QCOL: [xx].[dbo].[B].SomeColumn
*******************