在使用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表上为元组索引[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
问题是,如果你执行上面的查询,首先是约。比第二个快10倍。如果我们看一下实际的执行计划,我们可以看出差异的原因
Cursor完全省略现有索引,而是使用Index Scan,而“direct query”将三个“单独”结果集合并到具有适当索引用法的最终结果集中。
如果我在游标定义中更改“WHERE”部分,使其仅查看一个字段,它将使用适当的索引(由于游标的运行成本,它仍然较慢)。
有没有办法在不完全删除游标的情况下避免这种行为(因为在执行此操作的遗留应用程序中这是不可能的)?
由于
Martin 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>