3

我的数据仓库中有一个简单的查询(如下),为其创建了正确的索引。查询计划总是说估计的行数大约是 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' 更改为 >= '12/31/9999' 然后它使用哈希连接,但希望我更改大部分索引。

4

2 回答 2

1

请尝试添加option (recompile)到您的选择语句的末尾。

这应该会强制生成一个考虑到变量值的计划。

您可以尝试的另一个是option(optimize for unknown).

于 2013-04-17T06:44:55.443 回答
-1

我将此称为 SQL Server 2008 R2 (10.50.1400) 和 SQL Server 2012 (11.0.3000) 中的错误,因为没有人能够给我一个有效的答案。我最终改变了我所有的查询来使用

DWDateEnd >= '12/31/9999'

(注意添加大于)因为这会导致 SQL Server 使用散列连接而不是嵌套循环,并且查询速度更快。

我最终使用了一种解决方法,它添加了一个名为 DWActive 的持久计算位列(如果 DWDateEnd = '12/31/9999' 然后 1 否则为 0)。一旦我添加了该列和相应的索引,一切都会好得多。

于 2013-04-23T15:57:41.517 回答