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

Yos*_*ari 19 sql-server-2008 sql-server

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

SELECT *
FROM   A
WHERE  A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B) 
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 25

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

查询的执行计划的形状当然会有所不同,具体取决于表中有多少行以及定义了哪些索引。
一种表明性能没有差异的场景是 in 中的行数A远多于 in 中的行数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
*******************
Run Code Online (Sandbox Code Playgroud)

使用不同的查询的输入树和简化树:

*** 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
*******************
Run Code Online (Sandbox Code Playgroud)