我的数据仓库中有一个简单的查询(下面),为其创建了正确的索引。查询计划总是说估计的行数大约是1或2,大约应该是6,000,000左右。我运行了sp_updatestats'resample'并检查了统计直方图,它为EQ_ROWS显示了6,000,000,其中DWDateEnd = 12/31/9999,所以我很难过。所有表中99%的行的DWDateEnd为12/31/9999。如果我删除DWDateEnd过滤器,估计的行数将变得相当准确。它似乎通过引入嵌套循环来减慢我的查询,它应该在散列连接中进行。救命啊!
SELECT r.OrderID
FROM DWOrders r
JOIN DWOrderStatus rs ON r.OrderID = rs.OrderID AND rs.StatusID = 5 AND rs.ExpiredDate IS NULL
WHERE rs.StatusTimeStamp BETWEEN @StartDate AND @EndDate AND r.DWDateEnd = '12/31/9999'
AND rs.DWDateEnd = '12/31/9999'
这是执行计划。
<?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.4000.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="3" StatementEstRows="2.48996" StatementId="3" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.00817222" StatementText="
SELECT r.OrderID
 FROM DWOrder r
 JOIN DWOrderStatus rs ON r.OrderID = rs.OrderID AND rs.StatusID = 5 AND rs.ExpiredDate IS NULL AND rs.DWDateEnd = '12/31/9999' 
 WHERE rs.StatusTimeStamp BETWEEN @StartDate AND @EndDate AND r.DWDateEnd = '12/31/9999' 

" StatementType="SELECT" QueryHash="0x24DFCAFA0E610FB3" QueryPlanHash="0x6DD5D50E203E6273">
<StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
<QueryPlan CachedPlanSize="24" CompileTime="6" CompileCPU="6" CompileMemory="472">
<RelOp AvgRowSize="11" EstimateCPU="1.0408E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="2.48996" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.00817222">
<OutputList>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrder]" Alias="[r]" Column="OrderID" />
</OutputList>
<NestedLoops Optimized="false">
<OuterReferences>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="OrderID" />
</OuterReferences>
<RelOp AvgRowSize="11" EstimateCPU="0.000159131" EstimateIO="0.003125" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1.93725" LogicalOp="Index Seek" NodeId="1" Parallel="false" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.00328413" TableCardinality="24961700">
<OutputList>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="OrderID" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="OrderID" />
</DefinedValue>
</DefinedValues>
<Object Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Index="[IX_DWOrderStatus_DWDateEnd_ExpiredDate_SID_STS_RID]" Alias="[rs]" IndexKind="NonClustered" />
<SeekPredicates>
<SeekPredicateNew>
<SeekKeys>
<Prefix ScanType="EQ">
<RangeColumns>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="DWDateEnd" />
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="ExpiredDate" />
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="StatusID" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="'9999-12-31 00:00:00.000'">
<Const ConstValue="'9999-12-31 00:00:00.000'" />
</ScalarOperator>
<ScalarOperator ScalarString="NULL">
<Const ConstValue="NULL" />
</ScalarOperator>
<ScalarOperator ScalarString="(5)">
<Const ConstValue="(5)" />
</ScalarOperator>
</RangeExpressions>
</Prefix>
<StartRange ScanType="GE">
<RangeColumns>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="StatusTimeStamp" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="[@StartDate]">
<Identifier>
<ColumnReference Column="@StartDate" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</StartRange>
<EndRange ScanType="LE">
<RangeColumns>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="StatusTimeStamp" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="[@EndDate]">
<Identifier>
<ColumnReference Column="@EndDate" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</EndRange>
</SeekKeys>
</SeekPredicateNew>
</SeekPredicates>
</IndexScan>
</RelOp>
<RelOp AvgRowSize="11" EstimateCPU="0.000158414" EstimateIO="0.003125" EstimateRebinds="0.937251" EstimateRewinds="0" EstimateRows="1.28531" LogicalOp="Index Seek" NodeId="2" Parallel="false" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.00487768" TableCardinality="8048090">
<OutputList>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrder]" Alias="[r]" Column="OrderID" />
</OutputList>
<IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrder]" Alias="[r]" Column="OrderID" />
</DefinedValue>
</DefinedValues>
<Object Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrder]" Index="[IX_DWOrder_DWDateEnd]" Alias="[r]" IndexKind="NonClustered" />
<SeekPredicates>
<SeekPredicateNew>
<SeekKeys>
<Prefix ScanType="EQ">
<RangeColumns>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrder]" Alias="[r]" Column="DWDateEnd" />
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrder]" Alias="[r]" Column="OrderID" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="'9999-12-31 00:00:00.000'">
<Const ConstValue="'9999-12-31 00:00:00.000'" />
</ScalarOperator>
<ScalarOperator ScalarString="[EcommArchive].[dbo].[DWOrderStatus].[OrderID] as [rs].[OrderID]">
<Identifier>
<ColumnReference Database="[EcommArchive]" Schema="[dbo]" Table="[DWOrderStatus]" Alias="[rs]" Column="OrderID" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</Prefix>
</SeekKeys>
</SeekPredicateNew>
</SeekPredicates>
</IndexScan>
</RelOp>
</NestedLoops>
</RelOp>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
有趣的是,如果我将= '12 / 31/9999'更改为&gt; = '12 / 31/9999',那么它会使用散列连接,但希望我更改大部分索引。
答案 0 :(得分:1)
请尝试将option (recompile)
添加到select语句的末尾。
这应该强制生成一个考虑变量值的计划。
您可以尝试的另一个是option(optimize for unknown)
。
答案 1 :(得分:-1)
我称这是SQL Server 2008 R2(10.50.1400)和SQL Server 2012(11.0.3000)中的一个错误,因为没有人能够给我一个有效的答案。我最终改变了所有查询以使用
DWDateEnd&gt; = '12 / 31/9999'
(注意添加了Greater Than),因为这会导致SQL Server使用散列连接而不是嵌套循环,并且查询速度更快。
我最终使用了一种解决方法,即添加一个名为DWActive的持久计算位列(如果DWDateEnd = '12 / 31/9999',则其他为0)。一旦我添加了该列和相应的索引,一切都好多了。