如何正确索引多个字段以获得更快的结果

时间:2012-07-18 16:53:24

标签: sql performance sql-server-2008 rdbms indexing

我有一个包含ConChainNum,Control和TransDate的索引,我刚刚重建了索引。我正在使用的表有超过1亿条记录,以下查询没有返回任何结果:

select  * from sbt_pos_sales 
where   conchainnum = 810 and 
        control = 852013688 and 
        transdate = 20120712

鉴于我有一个专门针对where子句中的三个字段的索引,我真的希望得到一个几乎立即的结果,但是花了大约半分钟告诉我那里没有结果。

有人可以向我解释为什么这个索引没有比这更快,如果我能以某种方式做到不同以使其更快?

执行计划:

<?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.1" Build="10.0.5500.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="20.2265" StatementId="1" StatementOptmLevel="FULL" StatementSubTreeCost="348.687" StatementText="SELECT * FROM [ngdwdb]..[sbt_pos_sales] WHERE [conchainnum]=@1 AND [control]=@2 AND [transdate]=@3" StatementType="SELECT" QueryHash="0x11B117D9A8C6DF58" QueryPlanHash="0xBA3EFC04623601F6">
          <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="8" MemoryGrant="5504" CachedPlanSize="48" CompileTime="95" CompileCPU="4" CompileMemory="368">
            <RelOp AvgRowSize="193" EstimateCPU="0.0655713" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="7330.87" LogicalOp="Gather Streams" NodeId="1" Parallel="true" PhysicalOp="Parallelism" EstimatedTotalSubtreeCost="348.686">
              <OutputList>
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="RowIdent" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ConChainNum" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Control" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="TransDate" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ControlGS" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="UPC_UCP" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DateSold" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Price_UCP" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Store" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="QtySold" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="FileName" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="IssueCode" />
                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DealerNum" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
              </RunTimeInformation>
              <Parallelism>
                <RelOp AvgRowSize="193" EstimateCPU="0.00766076" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="7330.87" LogicalOp="Inner Join" NodeId="2" Parallel="true" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="348.621">
                  <OutputList>
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="RowIdent" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ConChainNum" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Control" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="TransDate" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ControlGS" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="UPC_UCP" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DateSold" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Price_UCP" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Store" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="QtySold" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="FileName" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="IssueCode" />
                    <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DealerNum" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="6" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="2" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="3" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="7" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="5" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="4" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="8" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="1" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                    <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                  </RunTimeInformation>
                  <NestedLoops Optimized="true" WithUnorderedPrefetch="true">
                    <OuterReferences>
                      <ColumnReference Column="Bmk1000" />
                      <ColumnReference Column="Expr1009" />
                    </OuterReferences>
                    <RelOp AvgRowSize="58" EstimateCPU="14.9196" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="7330.87" LogicalOp="Compute Scalar" NodeId="5" Parallel="true" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="324.579">
                      <OutputList>
                        <ColumnReference Column="Bmk1000" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ConChainNum" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Control" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="TransDate" />
                        <ColumnReference Column="Expr1008" />
                      </OutputList>
                      <ComputeScalar>
                        <DefinedValues>
                          <DefinedValue>
                            <ColumnReference Column="Expr1008" />
                            <ScalarOperator ScalarString="BmkToPage([Bmk1000])">
                              <Intrinsic FunctionName="BmkToPage">
                                <ScalarOperator>
                                  <Identifier>
                                    <ColumnReference Column="Bmk1000" />
                                  </Identifier>
                                </ScalarOperator>
                              </Intrinsic>
                            </ScalarOperator>
                          </DefinedValue>
                        </DefinedValues>
                        <RelOp AvgRowSize="58" EstimateCPU="15.196" EstimateIO="294.463" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="7330.87" LogicalOp="Index Seek" NodeId="6" Parallel="true" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="309.659" TableCardinality="107302000">
                          <OutputList>
                            <ColumnReference Column="Bmk1000" />
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ConChainNum" />
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Control" />
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="TransDate" />
                          </OutputList>
                          <RunTimeInformation>
                            <RunTimeCountersPerThread Thread="6" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="3" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="2" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="7" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="8" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="5" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="1" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="4" ActualRows="0" ActualEndOfScans="1" ActualExecutions="1" />
                            <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                          </RunTimeInformation>
                          <IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
                            <DefinedValues>
                              <DefinedValue>
                                <ColumnReference Column="Bmk1000" />
                              </DefinedValue>
                              <DefinedValue>
                                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ConChainNum" />
                              </DefinedValue>
                              <DefinedValue>
                                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Control" />
                              </DefinedValue>
                              <DefinedValue>
                                <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="TransDate" />
                              </DefinedValue>
                            </DefinedValues>
                            <Object Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Index="[idxLoad]" IndexKind="NonClustered" />
                            <SeekPredicates>
                              <SeekPredicateNew>
                                <SeekKeys>
                                  <Prefix ScanType="EQ">
                                    <RangeColumns>
                                      <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ConChainNum" />
                                    </RangeColumns>
                                    <RangeExpressions>
                                      <ScalarOperator ScalarString="(810)">
                                        <Const ConstValue="(810)" />
                                      </ScalarOperator>
                                    </RangeExpressions>
                                  </Prefix>
                                </SeekKeys>
                              </SeekPredicateNew>
                            </SeekPredicates>
                            <Predicate>
                              <ScalarOperator ScalarString="CONVERT_IMPLICIT(int,[NGDWDB].[dbo].[SBT_POS_SALES].[Control],0)=(852013688) AND CONVERT_IMPLICIT(int,[NGDWDB].[dbo].[SBT_POS_SALES].[TransDate],0)=(20120712)">
                                <Logical Operation="AND">
                                  <ScalarOperator>
                                    <Compare CompareOp="EQ">
                                      <ScalarOperator>
                                        <Convert DataType="int" Style="0" Implicit="true">
                                          <ScalarOperator>
                                            <Identifier>
                                              <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Control" />
                                            </Identifier>
                                          </ScalarOperator>
                                        </Convert>
                                      </ScalarOperator>
                                      <ScalarOperator>
                                        <Const ConstValue="(852013688)" />
                                      </ScalarOperator>
                                    </Compare>
                                  </ScalarOperator>
                                  <ScalarOperator>
                                    <Compare CompareOp="EQ">
                                      <ScalarOperator>
                                        <Convert DataType="int" Style="0" Implicit="true">
                                          <ScalarOperator>
                                            <Identifier>
                                              <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="TransDate" />
                                            </Identifier>
                                          </ScalarOperator>
                                        </Convert>
                                      </ScalarOperator>
                                      <ScalarOperator>
                                        <Const ConstValue="(20120712)" />
                                      </ScalarOperator>
                                    </Compare>
                                  </ScalarOperator>
                                </Logical>
                              </ScalarOperator>
                            </Predicate>
                          </IndexScan>
                        </RelOp>
                      </ComputeScalar>
                    </RelOp>
                    <RelOp AvgRowSize="136" EstimateCPU="0.0001581" EstimateIO="0.003125" EstimateRebinds="7329.87" EstimateRewinds="0" EstimateRows="1" LogicalOp="RID Lookup" NodeId="11" Parallel="true" PhysicalOp="RID Lookup" EstimatedTotalSubtreeCost="24.0341" TableCardinality="107302000">
                      <OutputList>
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="RowIdent" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ControlGS" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="UPC_UCP" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DateSold" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Price_UCP" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Store" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="QtySold" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="FileName" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="IssueCode" />
                        <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DealerNum" />
                      </OutputList>
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread="6" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="2" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="3" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="7" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="5" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="4" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="8" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="1" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                        <RunTimeCountersPerThread Thread="0" ActualRows="0" ActualEndOfScans="0" ActualExecutions="0" />
                      </RunTimeInformation>
                      <IndexScan Lookup="true" Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" NoExpandHint="false">
                        <DefinedValues>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="RowIdent" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="ControlGS" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="UPC_UCP" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DateSold" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Price_UCP" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="Store" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="QtySold" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="FileName" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="IssueCode" />
                          </DefinedValue>
                          <DefinedValue>
                            <ColumnReference Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" Column="DealerNum" />
                          </DefinedValue>
                        </DefinedValues>
                        <Object Database="[NGDWDB]" Schema="[dbo]" Table="[SBT_POS_SALES]" TableReferenceId="-1" IndexKind="Heap" />
                        <SeekPredicates>
                          <SeekPredicateNew>
                            <SeekKeys>
                              <Prefix ScanType="EQ">
                                <RangeColumns>
                                  <ColumnReference Column="Bmk1000" />
                                </RangeColumns>
                                <RangeExpressions>
                                  <ScalarOperator ScalarString="[Bmk1000]">
                                    <Identifier>
                                      <ColumnReference Column="Bmk1000" />
                                    </Identifier>
                                  </ScalarOperator>
                                </RangeExpressions>
                              </Prefix>
                            </SeekKeys>
                          </SeekPredicateNew>
                        </SeekPredicates>
                      </IndexScan>
                    </RelOp>
                  </NestedLoops>
                </RelOp>
              </Parallelism>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@3" ParameterCompiledValue="(20120712)" ParameterRuntimeValue="(20120712)" />
              <ColumnReference Column="@2" ParameterCompiledValue="(852013688)" ParameterRuntimeValue="(852013688)" />
              <ColumnReference Column="@1" ParameterCompiledValue="(810)" ParameterRuntimeValue="(810)" />
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

1 个答案:

答案 0 :(得分:1)

我不会继续填写评论,而是将其正式化为答案......

根据您的执行计划,我建议在表上添加聚簇索引。很难100%确定发生了什么,但RID查找是一个问题。

当没有与表关联的集群密钥时,会发生RID查找。在非聚簇索引中,如果存在聚簇键,则会在非聚簇索引中复制聚类键,从而在找到索引条目后加快所需的任何行访问。在堆(具有非聚集索引的表)中,您没有该聚簇键,因此您必须在堆中查找它。

这就是为什么执行计划中有INNER JOIN的原因,即使SQL中没有JOIN。将聚类应用于表中的主键应该消除此连接,并使用简单的索引查找。

虽然目前的计划显示它现在燃烧了89%的时间,但我敢打赌,通过桌面上的聚集索引,您可以将其简化为简单(并且更快)的索引搜索。

编辑:

让我在查看您的执行计划XML后对此进行修改。虽然聚类键仍然有用,但真正的问题是索引中的数据类型。在索引上我正在展示

CONVERT_IMPLICIT(int,[NGDWDB].[dbo].[SBT_POS_SALES].[Control],0)=(852013688) AND CONVERT_IMPLICIT(int,[NGDWDB].[dbo].[SBT_POS_SALES].[TransDate],0)=(20120712)

,它告诉我Control和TransDate与您在查询中提供的数据类型不同。如果你解决这个问题,不需要转换,你很可能会在查询中看到一个巨大的加速。