1

SQL Server 2008 で ADO ドライバーを使用している場合 (または、ドライバーによって作成された特定の SQL カーソルを使用している場合) に、興味深い「問題」が見つかりました。次のクエリを実行します。

SELECT ID, TelEveID, TelDayID, TelMobID, QualityFlag, WeekBegin FROM CEF 
WHERE (TelEveID = '+44xxxx') OR (TelDayID = '+44xxxxx') OR (TelMobID = '+44xxxx') 
ORDER BY ID DESC

タプルの CEF テーブルでインデックスが作成された 3 つの場所 (例として) [ID; TelEveID]、[ID; TelDayID]、[ID; TelMobID]

上記のクエリは、次の方法でドライバーによって「変換」されます。

declare @p1 int
declare @p2 int
declare @p5 int
set @p5=4
declare @p6 int
set @p6=4
declare @p7 int
set @p7=-1
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'SELECT ID, TelEveID, TelDayID, TelMobID, QualityFlag, WeekBegin FROM CEF WHERE (TelEveID = ''+44xxxx'') OR (TelDayID = ''+44xxxx'') OR (TelMobID = ''+44xxxx'') ORDER BY ID DESC',@p5 output,@p6 output,@p7 output
exec sp_cursorfetch @p2,2,1,10

問題は、上記のクエリを実行すると、最初のクエリが約になることです。2 番目のものより 10 倍高速です。そして、実際の実行計画を見れば、違いの理由がわかります

実行計画

カーソルは既存のインデックスを完全に省略し、代わりにインデックス スキャンを使用しますが、「直接クエリ」は 3 つの「個別の」結果セットを適切なインデックス使用法で最終的なものにマージします。

カーソル定義内の「WHERE」部分を変更して、1 つのフィールドのみを検索すると、適切なインデックスが使用されます (カーソルのランニング コストが原因でさらに遅くなります)。

カーソルを完全に削除せずにこの動作を回避する方法はありますか (これは、このアクションを実行するレガシー アプリケーションでは不可能なためです)。

ありがとう

マーティン F.

これは (少し短縮 - CEF テーブルのすべての列に関する情報を削除しました) (xml) カーソル ベース クエリの実行プランです。

<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.1" Build="10.50.1617.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="6" StatementEstRows="3.3163" StatementId="1" StatementOptmLevel="FULL" StatementSubTreeCost="134.243" StatementText="SELECT ID, TelEveID, TelDayID, TelMobID, QualityFlag, WeekBegin FROM CEF WHERE (TelEveID = '+44xxxx') OR (TelDayID = '+44xxxx') OR (TelMobID = '+44xxxx') ORDER BY ID DESC" StatementType="DECLARE CURSOR" QueryHash="0x4DC45EB62BCCAE06" QueryPlanHash="0x72ACC7B98E06E06E">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan DegreeOfParallelism="0" CachedPlanSize="152" CompileTime="7" CompileCPU="3" CompileMemory="992">
            <RelOp AvgRowSize="913" EstimateCPU="3.3163E-06" EstimateIO="0.01" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3.3163" LogicalOp="Insert" NodeId="0" Parallel="false" PhysicalOp="Clustered Index Insert" EstimatedTotalSubtreeCost="134.243">
              <OutputList>
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                <ColumnReference Column="Expr1005" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="1" />
              </RunTimeInformation>
              <Update DMLRequestSort="false">
                <Object Database="[tempdb]" Index="[CWT_PrimaryKey]" />
                <SetPredicate>
                  <ScalarOperator ScalarString="[CWT].[COLUMN0] = [LMS].[dbo].[CEF].[ID],[CWT].[CHECKSUM1] = [Chk1002],[CWT].[ROWID] = [Expr1005]">
                    <ScalarExpressionList>
                      <ScalarOperator>
                        <MultipleAssign>
                          <Assign>
                            <ColumnReference Table="[CWT]" Column="COLUMN0" />
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                              </Identifier>
                            </ScalarOperator>
                          </Assign>
                          <Assign>
                            <ColumnReference Table="[CWT]" Column="CHECKSUM1" />
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Column="Chk1002" />
                              </Identifier>
                            </ScalarOperator>
                          </Assign>
                          <Assign>
                            <ColumnReference Table="[CWT]" Column="ROWID" />
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Column="Expr1005" />
                              </Identifier>
                            </ScalarOperator>
                          </Assign>
                        </MultipleAssign>
                      </ScalarOperator>
                    </ScalarExpressionList>
                  </ScalarOperator>
                </SetPredicate>
                <RelOp AvgRowSize="917" EstimateCPU="3.3163E-07" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3.3163" LogicalOp="Compute Scalar" NodeId="1" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="134.233">
                  <OutputList>
                    <ColumnReference Column="Chk1002" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                    <ColumnReference Column="Expr1005" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="1" />
                  </RunTimeInformation>
                  <ComputeScalar>
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Column="Expr1005" />
                        <ScalarOperator ScalarString="CWT_ROWID()">
                          <Intrinsic FunctionName="CWT_ROWID" />
                        </ScalarOperator>
                      </DefinedValue>
                    </DefinedValues>
                    <RelOp AvgRowSize="913" EstimateCPU="1.68105" EstimateIO="130.748" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3.3163" LogicalOp="Clustered Index Scan" NodeId="2" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="132.429" TableCardinality="1528090">
                      <OutputList>
                        <ColumnReference Column="Chk1002" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                      </OutputList>
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="1" />
                      </RunTimeInformation>
                      <IndexScan Ordered="true" ScanDirection="BACKWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
                        <DefinedValues>
                          <DefinedValue>
                            <ColumnReference Column="Chk1002" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                          </DefinedValue>
                        </DefinedValues>
                        <Object Database="[LMS]" Schema="[dbo]" Table="[CEF]" Index="[PK_CEF]" IndexKind="Clustered" />
                        <Predicate>
                          <ScalarOperator ScalarString="[LMS].[dbo].[CEF].[TelEveID]='+44xxxx' OR [LMS].[dbo].[CEF].[TelDayID]='+44xxxx' OR [LMS].[dbo].[CEF].[TelMobID]='+44xxxx'">
                            <Logical Operation="OR">
                              <ScalarOperator>
                                <Compare CompareOp="EQ">
                                  <ScalarOperator>
                                    <Identifier>
                                      <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                                    </Identifier>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Const ConstValue="'+44xxxx'" />
                                  </ScalarOperator>
                                </Compare>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Compare CompareOp="EQ">
                                  <ScalarOperator>
                                    <Identifier>
                                      <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                                    </Identifier>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Const ConstValue="'+44xxxx'" />
                                  </ScalarOperator>
                                </Compare>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Compare CompareOp="EQ">
                                  <ScalarOperator>
                                    <Identifier>
                                      <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                                    </Identifier>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Const ConstValue="'+44xxxx'" />
                                  </ScalarOperator>
                                </Compare>
                              </ScalarOperator>
                            </Logical>
                          </ScalarOperator>
                        </Predicate>
                      </IndexScan>
                    </RelOp>
                  </ComputeScalar>
                </RelOp>
              </Update>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="7" StatementEstRows="3.3163" StatementId="2" StatementOptmLevel="FULL" StatementSubTreeCost="134.243" StatementText="FETCH API_CURSOR000000000007AA17" StatementType="FETCH CURSOR" QueryHash="0x4DC45EB62BCCAE06" QueryPlanHash="0x72ACC7B98E06E06E">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan DegreeOfParallelism="0" CachedPlanSize="152" CompileTime="7" CompileCPU="3" CompileMemory="992">
            <RelOp AvgRowSize="913" EstimateCPU="3.3163E-06" EstimateIO="0.01" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3.3163" LogicalOp="Insert" NodeId="0" Parallel="false" PhysicalOp="Clustered Index Insert" EstimatedTotalSubtreeCost="134.243">
              <OutputList>
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                <ColumnReference Column="Expr1005" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="1" ActualEndOfScans="1" ActualExecutions="1" />
              </RunTimeInformation>
              <Update DMLRequestSort="false">
                <Object Database="[tempdb]" Index="[CWT_PrimaryKey]" />
                <SetPredicate>
                  <ScalarOperator ScalarString="[CWT].[COLUMN0] = [LMS].[dbo].[CEF].[ID],[CWT].[CHECKSUM1] = [Chk1002],[CWT].[ROWID] = [Expr1005]">
                    <ScalarExpressionList>
                      <ScalarOperator>
                        <MultipleAssign>
                          <Assign>
                            <ColumnReference Table="[CWT]" Column="COLUMN0" />
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                              </Identifier>
                            </ScalarOperator>
                          </Assign>
                          <Assign>
                            <ColumnReference Table="[CWT]" Column="CHECKSUM1" />
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Column="Chk1002" />
                              </Identifier>
                            </ScalarOperator>
                          </Assign>
                          <Assign>
                            <ColumnReference Table="[CWT]" Column="ROWID" />
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Column="Expr1005" />
                              </Identifier>
                            </ScalarOperator>
                          </Assign>
                        </MultipleAssign>
                      </ScalarOperator>
                    </ScalarExpressionList>
                  </ScalarOperator>
                </SetPredicate>
                <RelOp AvgRowSize="917" EstimateCPU="3.3163E-07" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3.3163" LogicalOp="Compute Scalar" NodeId="1" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="134.233">
                  <OutputList>
                    <ColumnReference Column="Chk1002" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                    <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                    <ColumnReference Column="Expr1005" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="1" ActualEndOfScans="1" ActualExecutions="1" />
                  </RunTimeInformation>
                  <ComputeScalar>
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Column="Expr1005" />
                        <ScalarOperator ScalarString="CWT_ROWID()">
                          <Intrinsic FunctionName="CWT_ROWID" />
                        </ScalarOperator>
                      </DefinedValue>
                    </DefinedValues>
                    <RelOp AvgRowSize="913" EstimateCPU="1.68105" EstimateIO="130.748" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="3.3163" LogicalOp="Clustered Index Scan" NodeId="2" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="132.429" TableCardinality="1528090">
                      <OutputList>
                        <ColumnReference Column="Chk1002" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                        <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                      </OutputList>
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread="0" ActualRows="1" ActualEndOfScans="1" ActualExecutions="1" />
                      </RunTimeInformation>
                      <IndexScan Ordered="true" ScanDirection="BACKWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
                        <DefinedValues>
                          <DefinedValue>
                            <ColumnReference Column="Chk1002" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="ID" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                          </DefinedValue>
                        </DefinedValues>
                        <Object Database="[LMS]" Schema="[dbo]" Table="[CEF]" Index="[PK_CEF]" IndexKind="Clustered" />
                        <Predicate>
                          <ScalarOperator ScalarString="[LMS].[dbo].[CEF].[TelEveID]='+44xxxx' OR [LMS].[dbo].[CEF].[TelDayID]='+44xxxx' OR [LMS].[dbo].[CEF].[TelMobID]='+44xxxx'">
                            <Logical Operation="OR">
                              <ScalarOperator>
                                <Compare CompareOp="EQ">
                                  <ScalarOperator>
                                    <Identifier>
                                      <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelEveID" />
                                    </Identifier>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Const ConstValue="'+44xxxx'" />
                                  </ScalarOperator>
                                </Compare>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Compare CompareOp="EQ">
                                  <ScalarOperator>
                                    <Identifier>
                                      <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelDayID" />
                                    </Identifier>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Const ConstValue="'+44xxxx'" />
                                  </ScalarOperator>
                                </Compare>
                              </ScalarOperator>
                              <ScalarOperator>
                                <Compare CompareOp="EQ">
                                  <ScalarOperator>
                                    <Identifier>
                                      <ColumnReference Database="[LMS]" Schema="[dbo]" Table="[CEF]" Column="TelMobID" />
                                    </Identifier>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Const ConstValue="'+44xxxx'" />
                                  </ScalarOperator>
                                </Compare>
                              </ScalarOperator>
                            </Logical>
                          </ScalarOperator>
                        </Predicate>
                      </IndexScan>
                    </RelOp>
                  </ComputeScalar>
                </RelOp>
              </Update>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>
4

0 に答える 0