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>