一尘不染

在子查询中使用 DISTINCT 作为提示有用吗?

sql-server

在下面的例子中添加DISTINCT对查询运行时间有影响吗?
有时将它用作提示是否明智?

SELECT *
FROM   A
WHERE  A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B) 

阅读 189

收藏
2022-11-24

共1个答案

一尘不染

当想知道这样的事情时,您应该比较查询的执行计划。

您的查询执行计划的形状当然会有所不同,具体取决于您的表中有多少行以及定义了哪些索引。
显示性能没有差异的一种情况是 中的行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
*******************
2022-11-24