Spa*_*440 8 sql-server execution-plan
我读过的任何地方都说估计操作员成本是估计 CPU 成本和估计 I/O 成本的总和。但是,在我看到的许多运营商中,情况并非如此。下面是一个例子:
SELECT Column2
INTO Object1
FROM Object2
WHERE Column3 >= Variable2
AND Column3 <= Variable1
AND ( Column4 = Variable5
OR Variable5 = ? )
Run Code Online (Sandbox Code Playgroud)
EstimateIO="0.01" EstimateCPU="0.000246492"
总和:0.010246492
然而,SSMS 将此 0.073823 显示为估计的运营商成本。我完全不知道这是如何计算的。下面是执行计划 xml(匿名)。Node Id 0 是有问题的节点。
<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.2" Build="11.0.6537.0">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementText="	SELECT Column2 INTO Object1 
	FROM Object2
	WHERE Column3>=Variable2 AND Column3<=Variable1 
	AND (Column4=Variable5 OR Variable5=?)

" StatementId="1" StatementCompId="7" StatementType="SELECT INTO" RetrievedFromCache="true" StatementSubTreeCost="0.405134" StatementEstRows="246.492" StatementOptmLevel="FULL" QueryHash="0x180DF38DFFFEAFA2" QueryPlanHash="0x45A4295471B90968" StatementOptmEarlyAbortReason="GoodEnoughPlanFound">
<StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="false" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false" />
<QueryPlan CachedPlanSize="48" CompileTime="23" CompileCPU="6" CompileMemory="360">
<MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
<OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="157286" EstimatedPagesCached="314572" EstimatedAvailableDegreeOfParallelism="16" />
<RelOp NodeId="0" PhysicalOp="Table Insert" LogicalOp="Insert" EstimateRows="246.492" EstimateIO="0.01" EstimateCPU="0.000246492" AvgRowSize="9" EstimatedTotalSubtreeCost="0.405134" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
<OutputList />
<Update DMLRequestSort="0">
<Object Table="Object1" />
<SetPredicate>
<ScalarOperator ScalarString="ScalarString1">
<ScalarExpressionList>
<ScalarOperator>
<MultipleAssign>
<Assign>
<ColumnReference Table="Object1" Column="Column2" />
<ScalarOperator>
<Identifier>
<ColumnReference Database="Database1" Schema="Schema1" Table="Object2" Column="Column2" />
</Identifier>
</ScalarOperator>
</Assign>
</MultipleAssign>
</ScalarOperator>
</ScalarExpressionList>
</ScalarOperator>
</SetPredicate>
<RelOp NodeId="1" PhysicalOp="Index Seek" LogicalOp="Index Seek" EstimateRows="246.492" EstimateIO="0.22831" EstimateCPU="0.103001" AvgRowSize="15" EstimatedTotalSubtreeCost="0.331311" TableCardinality="1.03883e+006" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
<OutputList>
<ColumnReference Database="Database1" Schema="Schema1" Table="Object2" Column="Column2" />
</OutputList>
<IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" ForceSeek="0" ForceScan="0" NoExpandHint="0" Storage="RowStore">
<DefinedValues>
<DefinedValue>
<ColumnReference Database="Database1" Schema="Schema1" Table="Object2" Column="Column2" />
</DefinedValue>
</DefinedValues>
<Object Database="Database1" Schema="Schema1" Table="Object2" Index="Index1" IndexKind="NonClustered" />
<SeekPredicates>
<SeekPredicateNew>
<SeekKeys>
<StartRange ScanType="GE">
<RangeColumns>
<ColumnReference Database="Database1" Schema="Schema1" Table="Object2" Column="Column3" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="ScalarString2">
<Identifier>
<ColumnReference Column="Column7" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</StartRange>
<EndRange ScanType="LE">
<RangeColumns>
<ColumnReference Database="Database1" Schema="Schema1" Table="Object2" Column="Column3" />
</RangeColumns>
<RangeExpressions>
<ScalarOperator ScalarString="ScalarString3">
<Identifier>
<ColumnReference Column="Column8" />
</Identifier>
</ScalarOperator>
</RangeExpressions>
</EndRange>
</SeekKeys>
</SeekPredicateNew>
</SeekPredicates>
<Predicate>
<ScalarOperator ScalarString="ScalarString4">
<Logical Operation="OR">
<ScalarOperator>
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Database="Database1" Schema="Schema1" Table="Object2" Column="Column4" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Column="Column9" />
</Identifier>
</ScalarOperator>
</Compare>
</ScalarOperator>
<ScalarOperator>
<Identifier>
<ColumnReference Column="Column10">
<ScalarOperator>
<Compare CompareOp="EQ">
<ScalarOperator>
<Identifier>
<ColumnReference Column="Column9" />
</Identifier>
</ScalarOperator>
<ScalarOperator>
<Const ConstValue="Value4" />
</ScalarOperator>
</Compare>
</ScalarOperator>
</ColumnReference>
</Identifier>
</ScalarOperator>
</Logical>
</ScalarOperator>
</Predicate>
</IndexScan>
</RelOp>
</Update>
</RelOp>
<ParameterList>
<ColumnReference Column="Column9" ParameterCompiledValue="Value1" />
</ParameterList>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
Run Code Online (Sandbox Code Playgroud)
编辑:意识到我没有发布一个精心设计的问题。这是问题:
给定示例计划,SSMS 和计划资源管理器使用什么公式或计算得出节点 0 的估计操作员成本 0.073823?
格兰特,我相信我的同事(丹尼斯·罗杰斯)和我已经回答了这个问题。这里显示了 SSMS 用于计算操作员成本和成本百分比的确定公式。
估计运算符成本 == @EstimatedTotalSubtreeCost - Sum(直接子级@EstimatedTotalSubtreeCost)
估计的操作员成本百分比 = 估计的操作员成本 / StmtSimple@StatementSubTreeCost * 100
我已经用几个计划对此进行了测试,这似乎是正确的。
为了将上述计算表示为 xpath,它变成:
@EstimatedTotalSubtreeCost - sum(./descendant::s:RelOp[1]/../s:RelOp/@EstimatedTotalSubtreeCost)
Run Code Online (Sandbox Code Playgroud)
总和找到 RelOp 类型的第一个后代,然后备份一个级别,获取该级别的所有 RelOp,并提取它们的 EstimatedTotalSubtreeCost。