读取/解释XML查询估计计划以获得估计行数

时间:2017-03-13 15:45:55

标签: c# .net sql-server sql-execution-plan

我试图在c#.NET

中以编程方式获取查询的估计行数

我正在设置

"SET SHOWPLAN_XML ON;";

在运行查询之前,获取估算计划。

在一个表上为简单select返回的内容包含大量数据,我在XML中看到EstimateRows属性存在3次。

对于JOIN多个表的查询EstimateRows存在的次数更多。

示例:

 <?xml version="1.0" encoding="UTF-8"?>
<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"         Version="1.5" Build="14.0.100.430">
 <BatchSequence>
  <Batch>
     <Statements>
        <StmtSimple StatementText="SELECT COUNT(DISTINCT co.Id) FROM Campaign &amp;#xd;&amp;#xa;as ca JOIN KPI_EmailOpened as eo ON eo.CampaignId = ca.Id JOIN Contact&amp;#xd;&amp;#xa; AS co ON co.Id = eo.ContactId &amp;#xd;&amp;#xa;WHERE co.FirstName = &amp;apos;John&amp;apos;" StatementId="1" StatementCompId="1" StatementType="SELECT" RetrievedFromCache="false" StatementSubTreeCost="2.98809" StatementEstRows="1" SecurityPolicyApplied="false" StatementOptmLevel="FULL" QueryHash="0x5E01ED198558D453" QueryPlanHash="0xBD8133A97EEAAC2C" CardinalityEstimationModelVersion="130">
           <StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false" />
           <QueryPlan NonParallelPlanReason="EstimatedDOPIsOne" CachedPlanSize="48" CompileTime="9" CompileCPU="9" CompileMemory="816">
              <MemoryGrantInfo SerialRequiredMemory="3072" SerialDesiredMemory="3104" />
              <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="17616030" EstimatedPagesCached="1101001" EstimatedAvailableDegreeOfParallelism="1" MaxCompileMemory="4603408" />
              <RelOp NodeId="1" PhysicalOp="Compute Scalar" LogicalOp="Compute Scalar" EstimateRows="1" EstimateIO="0" EstimateCPU="1e-007" AvgRowSize="11" EstimatedTotalSubtreeCost="2.98809" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                 <OutputList>
                    <ColumnReference Column="Expr1003" />
                 </OutputList>
                 <ComputeScalar>
                    <DefinedValues>
                       <DefinedValue>
                          <ColumnReference Column="Expr1003" />
                          <ScalarOperator ScalarString="CONVERT_IMPLICIT(int,[globalagg1005],0)">
                             <Convert DataType="int" Style="0" Implicit="1">
                                <ScalarOperator>
                                   <Identifier>
                                      <ColumnReference Column="globalagg1005" />
                                   </Identifier>
                                </ScalarOperator>
                             </Convert>
                          </ScalarOperator>
                       </DefinedValue>
                    </DefinedValues>
                    <RelOp NodeId="2" PhysicalOp="Stream Aggregate" LogicalOp="Aggregate" EstimateRows="1" EstimateIO="0" EstimateCPU="1.1e-006" AvgRowSize="15" EstimatedTotalSubtreeCost="2.98809" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                       <OutputList>
                          <ColumnReference Column="globalagg1005" />
                       </OutputList>
                       <StreamAggregate>
                          <DefinedValues>
                             <DefinedValue>
                                <ColumnReference Column="globalagg1005" />
                                <ScalarOperator ScalarString="SUM([partialagg1004])">
                                   <Aggregate Distinct="0" AggType="SUM">
                                      <ScalarOperator>
                                         <Identifier>
                                            <ColumnReference Column="partialagg1004" />
                                         </Identifier>
                                      </ScalarOperator>
                                   </Aggregate>
                                </ScalarOperator>
                             </DefinedValue>
                          </DefinedValues>
                          <RelOp NodeId="3" PhysicalOp="Hash Match" LogicalOp="Aggregate" EstimateRows="1" EstimateIO="0" EstimateCPU="0.00188442" AvgRowSize="15" EstimatedTotalSubtreeCost="2.98809" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Batch">
                             <OutputList>
                                <ColumnReference Column="partialagg1004" />
                             </OutputList>
                             <MemoryFractions Input="1" Output="1" />
                             <Hash>
                                <DefinedValues>
                                   <DefinedValue>
                                      <ColumnReference Column="partialagg1004" />
                                      <ScalarOperator ScalarString="COUNT(*)">
                                         <Aggregate Distinct="0" AggType="COUNT*" />
                                      </ScalarOperator>
                                   </DefinedValue>
                                </DefinedValues>
                                <HashKeysBuild />
                                <RelOp NodeId="5" PhysicalOp="Nested Loops" LogicalOp="Left Semi Join" EstimateRows="10934.3" EstimateIO="0" EstimateCPU="0.0457056" AvgRowSize="9" EstimatedTotalSubtreeCost="2.98609" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                                   <OutputList />
                                   <NestedLoops Optimized="0" WithUnorderedPrefetch="1">
                                      <OuterReferences>
                                         <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[Contact]" Alias="[co]" Column="Id" />
                                         <ColumnReference Column="Expr1013" />
                                      </OuterReferences>
                                      <RelOp NodeId="7" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="10934.4" EstimatedRowsRead="10934.4" EstimateIO="0.0601111" EstimateCPU="0.0121848" AvgRowSize="19" EstimatedTotalSubtreeCost="0.0722959" TableCardinality="1e+007" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                                         <OutputList>
                                            <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[Contact]" Alias="[co]" Column="Id" />
                                         </OutputList>
                                         <IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="0" ForceScan="0" NoExpandHint="0" Storage="RowStore">
                                            <DefinedValues>
                                               <DefinedValue>
                                                  <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[Contact]" Alias="[co]" Column="Id" />
                                               </DefinedValue>
                                            </DefinedValues>
                                            <Object Database="[mydb]" Schema="[dbo]" Table="[Contact]" Index="[IX_Contact_FirstName]" Alias="[co]" IndexKind="NonClustered" Storage="RowStore" />
                                            <SeekPredicates>
                                               <SeekPredicateNew>
                                                  <SeekKeys>
                                                     <Prefix ScanType="EQ">
                                                        <RangeColumns>
                                                           <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[Contact]" Alias="[co]" Column="FirstName" />
                                                        </RangeColumns>
                                                        <RangeExpressions>
                                                           <ScalarOperator ScalarString="&amp;apos;John&amp;apos;">
                                                              <Const ConstValue="&amp;apos;John&amp;apos;" />
                                                           </ScalarOperator>
                                                        </RangeExpressions>
                                                     </Prefix>
                                                  </SeekKeys>
                                               </SeekPredicateNew>
                                            </SeekPredicates>
                                         </IndexScan>
                                      </RelOp>
                                      <RelOp NodeId="8" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="1" EstimatedRowsRead="30.0011" EstimateIO="0.003125" EstimateCPU="0.000190001" AvgRowSize="9" EstimatedTotalSubtreeCost="2.86809" TableCardinality="2.95e+008" Parallel="0" EstimateRebinds="10933.4" EstimateRewinds="0" EstimatedExecutionMode="Row">
                                         <OutputList />
                                         <IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="0" ForceScan="0" NoExpandHint="0" Storage="RowStore">
                                            <DefinedValues />
                                            <Object Database="[mydb]" Schema="[dbo]" Table="[KPI_EmailOpened]" Index="[KPI_EmailOpened_NCIDX_ContactCampaign]" Alias="[eo]" IndexKind="NonClustered" Storage="RowStore" />
                                            <SeekPredicates>
                                               <SeekPredicateNew>
                                                  <SeekKeys>
                                                     <Prefix ScanType="EQ">
                                                        <RangeColumns>
                                                           <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[KPI_EmailOpened]" Alias="[eo]" Column="ContactId" />
                                                        </RangeColumns>
                                                        <RangeExpressions>
                                                           <ScalarOperator ScalarString="[mydb].[dbo].[Contact].[Id] as [co].[Id]">
                                                              <Identifier>
                                                                 <ColumnReference Database="[mydb]" Schema="[dbo]" Table="[Contact]" Alias="[co]" Column="Id" />
                                                              </Identifier>
                                                           </ScalarOperator>
                                                        </RangeExpressions>
                                                     </Prefix>
                                                  </SeekKeys>
                                               </SeekPredicateNew>
                                            </SeekPredicates>
                                         </IndexScan>
                                      </RelOp>
                                   </NestedLoops>
                                </RelOp>
                             </Hash>
                          </RelOp>
                       </StreamAggregate>
                    </RelOp>
                 </ComputeScalar>
              </RelOp>
           </QueryPlan>
        </StmtSimple>
     </Statements>
  </Batch>

其中大部分都显示1作为估算,除了两个非常接近实际结果:(约10500行)

<RelOp NodeId="5" PhysicalOp="Nested Loops" LogicalOp="Left Semi Join" EstimateRows="10934.3" EstimateIO="0" EstimateCPU="0.0457056" AvgRowSize="9" EstimatedTotalSubtreeCost="2.98609" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">

<RelOp NodeId="7" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="10934.4" EstimatedRowsRead="10934.4" EstimateIO="0.0601111" EstimateCPU="0.0121848" AvgRowSize="19" EstimatedTotalSubtreeCost="0.0722959" TableCardinality="1e+007" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">

我试图找到有关如何阅读这些数据的文章但却找不到多少。

您能告诉或指出一些解释如何阅读此XML以及如何获取任何查询的估计行数的文章吗?

1 个答案:

答案 0 :(得分:0)

当您进行计数时,我认为1是返回记录数的正确值。这也是节点1,是执行计划的汇总/最后一步(您从右到左阅读它们)。其他节点是中间节点,中间结果(例如10500)是计数的基础。