SQL Server:估计的查询成本与实际执行时间不对应

时间:2015-10-29 12:09:35

标签: sql-server performance

这是我的故事:我有一个长时间运行的查询,执行大约需要10秒。为了优化它,我创建了一个我认为可能有帮助的索引 - sys.dm_db_missing_index_group_stats系统视图也推荐了它的创建。

但是服务器决定不使用索引。出于好奇,我试图通过提示强制它 - 并且查询以0.5秒完成!

我试图找出服务器忽略索引的原因。我更新了查询中包含的所有表的统计信息,并使用fullscan来确定。但没有变化。

然后我发现了令人惊讶的事情:根据执行计划,原始查询(执行10s)的估计子树成本是0.675但是使用强制索引(执行0.5s)的查询的估计子树成本是3.28 - 请参阅包含执行计划的详细信息

如果我理解得很好,服务器会认为带有索引的执行计划比没有它的计划运行得慢得多,但实际情况则相反。差异非常大。怎么可能?

为确保实际执行时间,我已将STATISTICS TIME设置为开启并获得以下结果:

原始查询

SQL Server Execution Times:
   CPU time = 10766 ms,  elapsed time = 11046 ms.

使用强制索引查询:

 SQL Server Execution Times:
   CPU time = 203 ms,  elapsed time = 433 ms.

我已经谷歌搜索了一段时间但没有发现任何线索。我不认为并行性可以给出任何解释(参见Measuring Query Performance : "Execution Plan Query Cost" vs "Time Taken"),因为两个查询都以并行度= 1运行,并且"快速"查询不仅耗时短,而且CPU时间也很短。

我的环境:Windows Server 2012 R2 64位,SQL Server 2012(v11.0.5613.0),64GB RAM,16核。最大的表t_object有大约2500万行。

以下是批量运行的两个查询的执行计划,首先是原始查询,第二个是强制索引的查询:

Graphical execution plan

这是"框架部分" XML中的执行计划。在我发现如何不超过体型限制后,我可以提供一个完整的:

<?xml version="1.0" encoding="utf-16"?>
<BatchSequence>
<Batch>
  <Statements>
    <StmtSimple StatementCompId="3" StatementEstRows="241" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.675167" StatementText="SELECT TOP 241  t_Object.c_id AS id, t_Object.c_objectDefName AS objectDefName, t_Object.c_id AS display, t_Object.c_owner AS owner, t_Object.c_ownerDefName AS ownerDefName &#xA;, t_KPDokBase.c_typ, a_KPCisTypDokumentu0.c_nazev, t_KPDokBase.c_kpid, t_KPDokBase.c_pojistnik, t_KPDokBase.c_kpdatum, t_KPDokBase.c_urgentni, t_KPDokBase.c_poznamka&#xA; FROM t_KPDokBase LEFT JOIN t_KPCiselnik a_KPCisTypDokumentu0 ON t_KPDokBase.c_typ=a_KPCisTypDokumentu0.c_Id , t_Document, t_Object &#xA; WHERE t_Document.c_Id = t_KPDokBase.c_Id AND t_Object.c_Id = t_Document.c_Id AND ((t_Object.c_createDT &gt;= '20151021 10:16:04.875') AND (((t_KPDokBase.c_pravaTyp = '') OR (t_KPDokBase.c_pravaTyp &lt;&gt; 'zdravotni')))) AND t_Document.c_trashed=0 AND t_Document.c_versionType=1&#xA; --doba využití procesoru = 10531 ms, uplynulá doba = 10816 ms.&#xA;&#xA;" StatementType="SELECT" QueryHash="0x5B65E1C5AEEE1DB3" QueryPlanHash="0x3AEC766C66B98CA1" RetrievedFromCache="true">
      <QueryPlan DegreeOfParallelism="1" MemoryGrant="1376" CachedPlanSize="72" CompileTime="57" CompileCPU="57" CompileMemory="848">
        <MemoryGrantInfo SerialRequiredMemory="1024" SerialDesiredMemory="1376" RequiredMemory="1024" DesiredMemory="1376" RequestedMemory="1376" GrantWaitTime="0" GrantedMemory="1376" MaxUsedMemory="640" />
        <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="209569" EstimatedPagesCached="419139" EstimatedAvailableDegreeOfParallelism="8" />
        <RelOp AvgRowSize="271" EstimateCPU="2.41E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="241" LogicalOp="Top" NodeId="0" Parallel="false" PhysicalOp="Top" EstimatedTotalSubtreeCost="0.675167">
          <OutputList>
          </OutputList>
          <RunTimeInformation>
            <RunTimeCountersPerThread Thread="0" ActualRows="241" ActualEndOfScans="1" ActualExecutions="1" />
          </RunTimeInformation>
          <Top RowCount="false" IsPercent="false" WithTies="false">
            <TopExpression>
              <ScalarOperator ScalarString="(241)">
                <Const ConstValue="(241)" />
              </ScalarOperator>
            </TopExpression>
          </Top>
        </RelOp>
      </QueryPlan>
    </StmtSimple>
  </Statements>
</Batch>
<Batch>
  <Statements>
    <StmtSimple StatementCompId="4" StatementEstRows="241" StatementId="2" StatementOptmLevel="FULL" StatementSubTreeCost="3.28305" StatementText="SELECT TOP 241  t_Object.c_id AS id, t_Object.c_objectDefName AS objectDefName, t_Object.c_id AS display, t_Object.c_owner AS owner, t_Object.c_ownerDefName AS ownerDefName &#xA;, t_KPDokBase.c_typ, a_KPCisTypDokumentu0.c_nazev, t_KPDokBase.c_kpid, t_KPDokBase.c_pojistnik, t_KPDokBase.c_kpdatum, t_KPDokBase.c_urgentni, t_KPDokBase.c_poznamka&#xA; FROM t_KPDokBase LEFT JOIN t_KPCiselnik a_KPCisTypDokumentu0 ON t_KPDokBase.c_typ=a_KPCisTypDokumentu0.c_Id , t_Document, t_Object WITH (INDEX(IX_cdt_obdn_ow_owdn))&#xA; WHERE t_Document.c_Id = t_KPDokBase.c_Id AND t_Object.c_Id = t_Document.c_Id AND ((t_Object.c_createDT &lt;= '20151021 10:16:04.875') AND (((t_KPDokBase.c_pravaTyp = '') OR (t_KPDokBase.c_pravaTyp &lt;&gt; 'zdravotni')))) AND t_Document.c_trashed=0 AND t_Document.c_versionType=1&#xA;  --doba využití procesoru = 218 ms, uplynulá doba = 669 ms.&#xA;" StatementType="SELECT" QueryHash="0xED6590A88AF84552" QueryPlanHash="0x61ED516F58A6CB68" RetrievedFromCache="true">
      <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="1" MemoryGrant="2451104" CachedPlanSize="80" CompileTime="26" CompileCPU="26" CompileMemory="800">
        <MemoryGrantInfo SerialRequiredMemory="1536" SerialDesiredMemory="2451104" RequiredMemory="1536" DesiredMemory="2451104" RequestedMemory="2451104" GrantWaitTime="0" GrantedMemory="2451104" MaxUsedMemory="2632" />
        <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="209569" EstimatedPagesCached="419139" EstimatedAvailableDegreeOfParallelism="8" />
      </QueryPlan>
    </StmtSimple>
  </Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>

0 个答案:

没有答案