相同的查询 - 不同的执行计划

发布于 2024-11-05 13:03:01 字数 16622 浏览 0 评论 0原文

SQL 2008。
我有一个测试表:

create table Sale
(
    SaleId int identity(1, 1)
        constraint PK_Sale primary key,
    Test1 varchar(10) null,
    RowVersion rowversion not null
        constraint UQ_Sale_RowVersion unique
)

我用 10k 测试行填充它。

declare @RowCount int = 10000
while(@RowCount > 0)
begin
    insert Sale default values
    set @RowCount -= 1
end

我运行这两个查询:

-- Query #1

select *
from Sale
where RowVersion > 0x000000000001C310

-- Query #2

declare @LastVersion rowversion = 0x000000000001C310

select *
from Sale
where RowVersion > @LastVersion

我无法弄清楚为什么这两个查询有不同的执行计划。
查询 #1 是否针对 UQ_Sale_RowVersion 索引进行索引查找。
查询 #2 对 PK_Sale 进行索引扫描。

我希望查询 #2 执行索引查找。
我希望得到一些帮助。
谢谢。

[编辑]

尝试使用 datetime2 而不是 rowversion。同样的问题。

我也尝试强制使用索引(查询 #3),

select *
from Sale with (index = IX_Sale_RowVersion)
where RowVersion > @LastVersion

这似乎显示与查询 #1 相同的查询执行计划,但执行计划显示此查询 #3 是所有这 3 个查询中最昂贵的。

[编辑]执行计划:

<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"
              Version="1.1"
              Build="10.50.1600.1">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementText="-- Query #1&#xd;&#xa;&#xd;&#xa;select *&#xd;&#xa;from Sale&#xd;&#xa;where RowVersion &gt; 0x000000000001C310&#xd;&#xa;&#xd;&#xa;-- Query #2&#xd;&#xa;&#xd;"
                    StatementId="1"
                    StatementCompId="1"
                    StatementType="SELECT"
                    StatementSubTreeCost="0.00657038"
                    StatementEstRows="1"
                    StatementOptmLevel="FULL"
                    QueryHash="0xE442FF9A4A2A630A"
                    QueryPlanHash="0x347569CFDEF2A13F"
                    StatementOptmEarlyAbortReason="GoodEnoughPlanFound"
                    ParameterizedText="(@1 varbinary(8000))SELECT * FROM [Sale] WHERE [RowVersion]&gt;@1">
          <StatementSetOptions QUOTED_IDENTIFIER="true"
                                ARITHABORT="true"
                                CONCAT_NULL_YIELDS_NULL="true"
                                ANSI_NULLS="true"
                                ANSI_PADDING="true"
                                ANSI_WARNINGS="true"
                                NUMERIC_ROUNDABORT="false"/>
          <QueryPlan CachedPlanSize="24"
                      CompileTime="1"
                      CompileCPU="1"
                      CompileMemory="136">
            <RelOp NodeId="0"
                    PhysicalOp="Nested Loops"
                    LogicalOp="Inner Join"
                    EstimateRows="1"
                    EstimateIO="0"
                    EstimateCPU="4.18e-006"
                    AvgRowSize="28"
                    EstimatedTotalSubtreeCost="0.00657038"
                    Parallel="0"
                    EstimateRebinds="0"
                    EstimateRewinds="0">
              <OutputList>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="SaleId"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="Test1"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="RowVersion"/>
              </OutputList>
              <NestedLoops Optimized="0">
                <OuterReferences>
                  <ColumnReference Database="[AdventureWorks]"
                                    Schema="[dbo]"
                                    Table="[Sale]"
                                    Column="SaleId"/>
                </OuterReferences>
                <RelOp NodeId="1"
                        PhysicalOp="Index Seek"
                        LogicalOp="Index Seek"
                        EstimateRows="1"
                        EstimateIO="0.003125"
                        EstimateCPU="0.0001581"
                        AvgRowSize="19"
                        EstimatedTotalSubtreeCost="0.0032831"
                        TableCardinality="10000"
                        Parallel="0"
                        EstimateRebinds="0"
                        EstimateRewinds="0">
                  <OutputList>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="SaleId"/>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="RowVersion"/>
                  </OutputList>
                  <IndexScan Ordered="1"
                              ScanDirection="FORWARD"
                              ForcedIndex="0"
                              ForceSeek="0"
                              NoExpandHint="0">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks]"
                                          Schema="[dbo]"
                                          Table="[Sale]"
                                          Column="SaleId"/>
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks]"
                                          Schema="[dbo]"
                                          Table="[Sale]"
                                          Column="RowVersion"/>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[AdventureWorks]"
                            Schema="[dbo]"
                            Table="[Sale]"
                            Index="[UQ_Sale_RowVersion]"
                            IndexKind="NonClustered"/>
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <StartRange ScanType="GT">
                            <RangeColumns>
                              <ColumnReference Database="[AdventureWorks]"
                                                Schema="[dbo]"
                                                Table="[Sale]"
                                                Column="RowVersion"/>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="0x000000000001C310">
                                <Const ConstValue="0x000000000001C310"/>
                              </ScalarOperator>
                            </RangeExpressions>
                          </StartRange>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                  </IndexScan>
                </RelOp>
                <RelOp NodeId="3"
                        PhysicalOp="Clustered Index Seek"
                        LogicalOp="Clustered Index Seek"
                        EstimateRows="1"
                        EstimateIO="0.003125"
                        EstimateCPU="0.0001581"
                        AvgRowSize="16"
                        EstimatedTotalSubtreeCost="0.0032831"
                        TableCardinality="10000"
                        Parallel="0"
                        EstimateRebinds="0"
                        EstimateRewinds="0">
                  <OutputList>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="Test1"/>
                  </OutputList>
                  <IndexScan Lookup="1"
                              Ordered="1"
                              ScanDirection="FORWARD"
                              ForcedIndex="0"
                              ForceSeek="0"
                              NoExpandHint="0">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks]"
                                          Schema="[dbo]"
                                          Table="[Sale]"
                                          Column="Test1"/>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[AdventureWorks]"
                            Schema="[dbo]"
                            Table="[Sale]"
                            Index="[PK_Sale]"
                            TableReferenceId="-1"
                            IndexKind="Clustered"/>
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <Prefix ScanType="EQ">
                            <RangeColumns>
                              <ColumnReference Database="[AdventureWorks]"
                                                Schema="[dbo]"
                                                Table="[Sale]"
                                                Column="SaleId"/>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[AdventureWorks].[dbo].[Sale].[SaleId]">
                                <Identifier>
                                  <ColumnReference Database="[AdventureWorks]"
                                                    Schema="[dbo]"
                                                    Table="[Sale]"
                                                    Column="SaleId"/>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </Prefix>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                  </IndexScan>
                </RelOp>
              </NestedLoops>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@1"
                                ParameterCompiledValue="0x000000000001C310"/>
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
              <StmtSimple StatementText="&#xa;declare @LastVersion rowversion = 0x000000000001C310&#xd;&#xa;&#xd;"
                  StatementId="2"
                  StatementCompId="2"
                  StatementType="ASSIGN"/>
        <StmtSimple StatementText="&#xa;select *&#xd;&#xa;from Sale&#xd;&#xa;where RowVersion &gt; @LastVersion"
                    StatementId="3"
                    StatementCompId="3"
                    StatementType="SELECT"
                    StatementSubTreeCost="0.0328005"
                    StatementEstRows="3000"
                    StatementOptmLevel="FULL"
                    QueryHash="0xE442FF9A4A2A630A"
                    QueryPlanHash="0x0C6238F821406F2B"
                    StatementOptmEarlyAbortReason="GoodEnoughPlanFound">
          <StatementSetOptions QUOTED_IDENTIFIER="true"
                                ARITHABORT="true"
                                CONCAT_NULL_YIELDS_NULL="true"
                                ANSI_NULLS="true"
                                ANSI_PADDING="true"
                                ANSI_WARNINGS="true"
                                NUMERIC_ROUNDABORT="false"/>
          <QueryPlan CachedPlanSize="16"
                      CompileTime="1"
                      CompileCPU="1"
                      CompileMemory="144">
            <RelOp NodeId="0"
                    PhysicalOp="Clustered Index Scan"
                    LogicalOp="Clustered Index Scan"
                    EstimateRows="3000"
                    EstimateIO="0.0216435"
                    EstimateCPU="0.011157"
                    AvgRowSize="28"
                    EstimatedTotalSubtreeCost="0.0328005"
                    TableCardinality="10000"
                    Parallel="0"
                    EstimateRebinds="0"
                    EstimateRewinds="0">
              <OutputList>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="SaleId"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="Test1"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="RowVersion"/>
              </OutputList>
              <IndexScan Ordered="0"
                          ForcedIndex="0"
                          NoExpandHint="0">
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="SaleId"/>
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="Test1"/>
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="RowVersion"/>
                  </DefinedValue>
                </DefinedValues>
                <Object Database="[AdventureWorks]"
                        Schema="[dbo]"
                        Table="[Sale]"
                        Index="[PK_Sale]"
                        IndexKind="Clustered"/>
                <Predicate>
                  <ScalarOperator ScalarString="[AdventureWorks].[dbo].[Sale].[RowVersion]&gt;[@LastVersion]">
                    <Compare CompareOp="GT">
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Database="[AdventureWorks]"
                                            Schema="[dbo]"
                                            Table="[Sale]"
                                            Column="RowVersion"/>
                        </Identifier>
                      </ScalarOperator>
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Column="@LastVersion"/>
                        </Identifier>
                      </ScalarOperator>
                    </Compare>
                  </ScalarOperator>
                </Predicate>
              </IndexScan>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

SQL 2008.
I have a test table:

create table Sale
(
    SaleId int identity(1, 1)
        constraint PK_Sale primary key,
    Test1 varchar(10) null,
    RowVersion rowversion not null
        constraint UQ_Sale_RowVersion unique
)

I populate it with 10k test rows.

declare @RowCount int = 10000
while(@RowCount > 0)
begin
    insert Sale default values
    set @RowCount -= 1
end

I run these two queries:

-- Query #1

select *
from Sale
where RowVersion > 0x000000000001C310

-- Query #2

declare @LastVersion rowversion = 0x000000000001C310

select *
from Sale
where RowVersion > @LastVersion

I can't figure out why these two queries have different execution plan.
Query #1 does index seek against UQ_Sale_RowVersion index.
Query #2 does index scan against PK_Sale.

I want query #2 to do index seek.
I would appreciate some help.
Thank you.

[Edit]

Tried using datetime2 instead of rowversion. The same issue.

I tried to force using index too (query #3)

select *
from Sale with (index = IX_Sale_RowVersion)
where RowVersion > @LastVersion

This seemed to show the same query execution plan as the query #1, but execution plan showed this query #3 as the most expensive among all those 3 queries.

[Edit] Execution plan:

<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"
              Version="1.1"
              Build="10.50.1600.1">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementText="-- Query #1

select *
from Sale
where RowVersion > 0x000000000001C310

-- Query #2

"
                    StatementId="1"
                    StatementCompId="1"
                    StatementType="SELECT"
                    StatementSubTreeCost="0.00657038"
                    StatementEstRows="1"
                    StatementOptmLevel="FULL"
                    QueryHash="0xE442FF9A4A2A630A"
                    QueryPlanHash="0x347569CFDEF2A13F"
                    StatementOptmEarlyAbortReason="GoodEnoughPlanFound"
                    ParameterizedText="(@1 varbinary(8000))SELECT * FROM [Sale] WHERE [RowVersion]>@1">
          <StatementSetOptions QUOTED_IDENTIFIER="true"
                                ARITHABORT="true"
                                CONCAT_NULL_YIELDS_NULL="true"
                                ANSI_NULLS="true"
                                ANSI_PADDING="true"
                                ANSI_WARNINGS="true"
                                NUMERIC_ROUNDABORT="false"/>
          <QueryPlan CachedPlanSize="24"
                      CompileTime="1"
                      CompileCPU="1"
                      CompileMemory="136">
            <RelOp NodeId="0"
                    PhysicalOp="Nested Loops"
                    LogicalOp="Inner Join"
                    EstimateRows="1"
                    EstimateIO="0"
                    EstimateCPU="4.18e-006"
                    AvgRowSize="28"
                    EstimatedTotalSubtreeCost="0.00657038"
                    Parallel="0"
                    EstimateRebinds="0"
                    EstimateRewinds="0">
              <OutputList>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="SaleId"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="Test1"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="RowVersion"/>
              </OutputList>
              <NestedLoops Optimized="0">
                <OuterReferences>
                  <ColumnReference Database="[AdventureWorks]"
                                    Schema="[dbo]"
                                    Table="[Sale]"
                                    Column="SaleId"/>
                </OuterReferences>
                <RelOp NodeId="1"
                        PhysicalOp="Index Seek"
                        LogicalOp="Index Seek"
                        EstimateRows="1"
                        EstimateIO="0.003125"
                        EstimateCPU="0.0001581"
                        AvgRowSize="19"
                        EstimatedTotalSubtreeCost="0.0032831"
                        TableCardinality="10000"
                        Parallel="0"
                        EstimateRebinds="0"
                        EstimateRewinds="0">
                  <OutputList>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="SaleId"/>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="RowVersion"/>
                  </OutputList>
                  <IndexScan Ordered="1"
                              ScanDirection="FORWARD"
                              ForcedIndex="0"
                              ForceSeek="0"
                              NoExpandHint="0">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks]"
                                          Schema="[dbo]"
                                          Table="[Sale]"
                                          Column="SaleId"/>
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks]"
                                          Schema="[dbo]"
                                          Table="[Sale]"
                                          Column="RowVersion"/>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[AdventureWorks]"
                            Schema="[dbo]"
                            Table="[Sale]"
                            Index="[UQ_Sale_RowVersion]"
                            IndexKind="NonClustered"/>
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <StartRange ScanType="GT">
                            <RangeColumns>
                              <ColumnReference Database="[AdventureWorks]"
                                                Schema="[dbo]"
                                                Table="[Sale]"
                                                Column="RowVersion"/>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="0x000000000001C310">
                                <Const ConstValue="0x000000000001C310"/>
                              </ScalarOperator>
                            </RangeExpressions>
                          </StartRange>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                  </IndexScan>
                </RelOp>
                <RelOp NodeId="3"
                        PhysicalOp="Clustered Index Seek"
                        LogicalOp="Clustered Index Seek"
                        EstimateRows="1"
                        EstimateIO="0.003125"
                        EstimateCPU="0.0001581"
                        AvgRowSize="16"
                        EstimatedTotalSubtreeCost="0.0032831"
                        TableCardinality="10000"
                        Parallel="0"
                        EstimateRebinds="0"
                        EstimateRewinds="0">
                  <OutputList>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="Test1"/>
                  </OutputList>
                  <IndexScan Lookup="1"
                              Ordered="1"
                              ScanDirection="FORWARD"
                              ForcedIndex="0"
                              ForceSeek="0"
                              NoExpandHint="0">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks]"
                                          Schema="[dbo]"
                                          Table="[Sale]"
                                          Column="Test1"/>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[AdventureWorks]"
                            Schema="[dbo]"
                            Table="[Sale]"
                            Index="[PK_Sale]"
                            TableReferenceId="-1"
                            IndexKind="Clustered"/>
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <Prefix ScanType="EQ">
                            <RangeColumns>
                              <ColumnReference Database="[AdventureWorks]"
                                                Schema="[dbo]"
                                                Table="[Sale]"
                                                Column="SaleId"/>
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[AdventureWorks].[dbo].[Sale].[SaleId]">
                                <Identifier>
                                  <ColumnReference Database="[AdventureWorks]"
                                                    Schema="[dbo]"
                                                    Table="[Sale]"
                                                    Column="SaleId"/>
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </Prefix>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                  </IndexScan>
                </RelOp>
              </NestedLoops>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@1"
                                ParameterCompiledValue="0x000000000001C310"/>
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
              <StmtSimple StatementText="
declare @LastVersion rowversion = 0x000000000001C310

"
                  StatementId="2"
                  StatementCompId="2"
                  StatementType="ASSIGN"/>
        <StmtSimple StatementText="
select *
from Sale
where RowVersion > @LastVersion"
                    StatementId="3"
                    StatementCompId="3"
                    StatementType="SELECT"
                    StatementSubTreeCost="0.0328005"
                    StatementEstRows="3000"
                    StatementOptmLevel="FULL"
                    QueryHash="0xE442FF9A4A2A630A"
                    QueryPlanHash="0x0C6238F821406F2B"
                    StatementOptmEarlyAbortReason="GoodEnoughPlanFound">
          <StatementSetOptions QUOTED_IDENTIFIER="true"
                                ARITHABORT="true"
                                CONCAT_NULL_YIELDS_NULL="true"
                                ANSI_NULLS="true"
                                ANSI_PADDING="true"
                                ANSI_WARNINGS="true"
                                NUMERIC_ROUNDABORT="false"/>
          <QueryPlan CachedPlanSize="16"
                      CompileTime="1"
                      CompileCPU="1"
                      CompileMemory="144">
            <RelOp NodeId="0"
                    PhysicalOp="Clustered Index Scan"
                    LogicalOp="Clustered Index Scan"
                    EstimateRows="3000"
                    EstimateIO="0.0216435"
                    EstimateCPU="0.011157"
                    AvgRowSize="28"
                    EstimatedTotalSubtreeCost="0.0328005"
                    TableCardinality="10000"
                    Parallel="0"
                    EstimateRebinds="0"
                    EstimateRewinds="0">
              <OutputList>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="SaleId"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="Test1"/>
                <ColumnReference Database="[AdventureWorks]"
                                  Schema="[dbo]"
                                  Table="[Sale]"
                                  Column="RowVersion"/>
              </OutputList>
              <IndexScan Ordered="0"
                          ForcedIndex="0"
                          NoExpandHint="0">
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="SaleId"/>
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="Test1"/>
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database="[AdventureWorks]"
                                      Schema="[dbo]"
                                      Table="[Sale]"
                                      Column="RowVersion"/>
                  </DefinedValue>
                </DefinedValues>
                <Object Database="[AdventureWorks]"
                        Schema="[dbo]"
                        Table="[Sale]"
                        Index="[PK_Sale]"
                        IndexKind="Clustered"/>
                <Predicate>
                  <ScalarOperator ScalarString="[AdventureWorks].[dbo].[Sale].[RowVersion]>[@LastVersion]">
                    <Compare CompareOp="GT">
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Database="[AdventureWorks]"
                                            Schema="[dbo]"
                                            Table="[Sale]"
                                            Column="RowVersion"/>
                        </Identifier>
                      </ScalarOperator>
                      <ScalarOperator>
                        <Identifier>
                          <ColumnReference Column="@LastVersion"/>
                        </Identifier>
                      </ScalarOperator>
                    </Compare>
                  </ScalarOperator>
                </Predicate>
              </IndexScan>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不忘初心 2024-11-12 13:03:01

查询 2 使用变量。

在编译批处理时,SQL Server 不知道变量的值,因此只能退回到与 OPTIMIZE FOR (UNKNOWN) 非常相似的启发式方法,

对于 > 它将假设 30% 的行最终会匹配(或示例数据中的 3000 行)。这可以在如下的执行计划图中看到。这明显超出了 12 行 (0.12%),即 此查询的临界点是使用聚集索引扫描还是非聚集索引查找和键查找。

您需要使用 OPTION (RECOMPILE) 来使其考虑实际变量值,如下面的第三个计划所示。

执行计划图像

脚本

CREATE TABLE #Sale
(
    SaleId INT IDENTITY(1, 1)
        CONSTRAINT PK_Sale PRIMARY KEY,
    Test1 VARCHAR(10) NULL,
    RowVersion rowversion NOT NULL
        CONSTRAINT UQ_Sale_RowVersion UNIQUE
)

/*A better way of populating the table!*/
INSERT INTO #Sale (Test1)
SELECT TOP 10000 NULL 
FROM master..spt_values v1, master..spt_values v2

GO

SELECT *
FROM #Sale
WHERE RowVersion > 0x000000000001C310-- Query #1


DECLARE @LastVersion rowversion = 0x000000000001C310

SELECT *
FROM #Sale
WHERE RowVersion > @LastVersion-- Query #2


SELECT *
FROM #Sale
WHERE RowVersion > @LastVersion
OPTION (RECOMPILE)-- Query #3

DROP TABLE #Sale

Query 2 uses a variable.

At the time the batch is compiled SQL Server does not know the value of the variable so just falls back to heuristics very similar to OPTIMIZE FOR (UNKNOWN)

For > it will assume that 30% of the rows will end up matching (or 3000 rows in your example data). This can be seen in the execution plan image as below. This is significantly over and above the 12 rows (0.12%) which is the tipping point for this query in whether it uses a clustered index scan or a non clustered index seek and key lookups.

You would need to use OPTION (RECOMPILE) to get it to take account of the actual variable value as shown in the third plan below.

Execution Plans Image

Script

CREATE TABLE #Sale
(
    SaleId INT IDENTITY(1, 1)
        CONSTRAINT PK_Sale PRIMARY KEY,
    Test1 VARCHAR(10) NULL,
    RowVersion rowversion NOT NULL
        CONSTRAINT UQ_Sale_RowVersion UNIQUE
)

/*A better way of populating the table!*/
INSERT INTO #Sale (Test1)
SELECT TOP 10000 NULL 
FROM master..spt_values v1, master..spt_values v2

GO

SELECT *
FROM #Sale
WHERE RowVersion > 0x000000000001C310-- Query #1


DECLARE @LastVersion rowversion = 0x000000000001C310

SELECT *
FROM #Sale
WHERE RowVersion > @LastVersion-- Query #2


SELECT *
FROM #Sale
WHERE RowVersion > @LastVersion
OPTION (RECOMPILE)-- Query #3

DROP TABLE #Sale
怪我闹别瞎闹 2024-11-12 13:03:01

尝试为您需要检索的实际数据创建覆盖索引并避免 select *,具体取决于表中的数据,这是强制 SQL Server 不提示的唯一确定的事情< /em> 并回退到扫描。

覆盖索引是指搜索过滤器的顺序相同且每个输出列都包含在索引中的索引。

另外,由于我们正在处理参数化,因此值得尝试看看针对未知进行优化是否对这里的执行计划有任何影响。

Try creating a covering index for the actual data that you need to retrieve and avoid select *, depending on the data in your table that's the only sure thing that will force SQL Server to not tip and fallback to a scan.

A covering index is an index in which the search filter is in the same order and each output column is included in the index.

Also, since we're dealing with parameterization, it's worth trying to see if optimize for unknown has any impact on the execution plan here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文