尽管有效统计数据,查询计划估计行数仍然非常低

时间:2013-04-10 23:36:11

标签: sql-server sql-server-2008-r2 indexing

我的数据仓库中有一个简单的查询(下面),为其创建了正确的索引。查询计划总是说估计的行数大约是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="&#xA;SELECT r.OrderID&#xD;&#xA;           FROM DWOrder r&#xD;&#xA;            JOIN DWOrderStatus rs ON r.OrderID = rs.OrderID AND rs.StatusID = 5 AND rs.ExpiredDate IS NULL AND rs.DWDateEnd = '12/31/9999' &#xD;&#xA;           WHERE rs.StatusTimeStamp BETWEEN @StartDate AND @EndDate AND r.DWDateEnd = '12/31/9999' &#xD;&#xA;&#xD;&#xA;" 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',那么它会使用散列连接,但希望我更改大部分索引。

2 个答案:

答案 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)。一旦我添加了该列和相应的索引,一切都好多了。