Geschätzte Berechnung der Betreiberkosten

7

Überall, wo ich gelesen habe, heißt es, dass die geschätzten Betreiberkosten die Summe der geschätzten CPU-Kosten und der und der geschätzten E / A-Kosten sind. Bei vielen Betreibern ist dies jedoch nicht der Fall. Hier ist ein Beispiel:

SELECT Column2
INTO   Object1
FROM   Object2
WHERE  Column3 >= Variable2
       AND Column3 <= Variable1
       AND ( Column4 = Variable5
              OR Variable5 = ? ) 

Geben Sie hier die Bildbeschreibung ein

EstimateIO = "0.01" EstimateCPU = "0.000246492"

Summe: 0,010246492

SSMS zeigt diese 0,073823 jedoch als geschätzte Betreiberkosten an. Ich bin völlig ratlos, wie dies berechnet wird. Unten ist der Ausführungsplan xml (anonymisiert). Knoten-ID 0 ist der betreffende Knoten.

<?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="&#x9;SELECT Column2 INTO Object1 &#xD;&#xA;&#x9;FROM Object2&#xD;&#xA;&#x9;WHERE Column3&gt;=Variable2 AND Column3&lt;=Variable1 &#xD;&#xA;&#x9;AND (Column4=Variable5 OR Variable5=?)&#xD;&#xA;&#xD;&#xA;" 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>

EDIT: Es wurde mir klar, dass ich keine gut formulierte Frage gestellt habe. Hier ist die Frage:

Welche Formel oder Berechnung haben SSMS und Plan Explorer angesichts des Beispielplans verwendet, um die geschätzten Betreiberkosten von 0,073823 für Knoten 0 zu ermitteln?

SpaceGhost440
quelle
2
Der SQL Sentry-Plan-Explorer zeigt unterschiedliche Ergebnisse an. I.stack.imgur.com/uEo3m.png - sieht so aus, als müssten die Werte angepasst werden, um sie konsistent zu machen.
Martin Smith
Ja, ich benutze auch Plan Explorer Martin und habe das gesehen. Ich bin also sehr neugierig, wie haben sie das berechnet? Es sieht so aus, als ob die E / A-Kosten im Plan-Explorer angepasst wurden. Der Plan-Explorer zeigt dann genau die gleichen geschätzten Betriebskosten an. Wie hat Plan Explorer die Änderung an den E / A-Kosten vorgenommen, die zu den richtigen Betreiberkosten geführt haben?
SpaceGhost440

Antworten:

3

Die einzige Möglichkeit, diese Frage richtig zu beantworten, besteht darin, den Debugger zu starten und zu sehen, welche Entscheidungen der Optimierer auf dem Weg getroffen hat. Die Kosten sind nicht nur E / A und CPU. Mit einem bestimmten Betreiber sind zusätzliche Kosten verbunden, die sich in den Gesamtkosten widerspiegeln, jedoch nicht in den E / A- und CPU-Kostenschätzungen. Weitere Informationen zu den zusätzlichen Kosten finden Sie in diesem ausgezeichneten Artikel von Paul White . 🕗

Ich habe keine genaue Antwort auf Ihre Frage (ich habe keinen Zweifel, Paul würde). Ich bin jedoch bereit, eine Vermutung anzustellen. Was Sie sehen, ist ein zusätzlicher Overhead für den Vorgang, der vom Optimierer festgelegt wird, und zwar über den Overhead für den E / A und die CPU hinaus, der durch die geschätzten Zeilen usw. bestimmt wird. Ich glaube, es handelt sich um eine Berechnung, die auf dem basiert, was würde In Bezug auf E / A erforderlich, um die Tabelle zu erstellen und die Daten im Wert von 246.492 Zeilen * 9b zu speichern, die jeweils in der INSERT-Anweisung berechnet werden. 246.492 * 9/1024 = 2.1664 ist weniger als eine 8-KB-Seite. Wir müssen jedoch mindestens eine Seite erstellen. Wenn Sie also 8 * der Kosten von 0,01 berechnen, liegen wir nur ein wenig über dem geschätzten Wert von 0,073832. Das ist meine Vermutung, und es ist eine Vermutung. Ich weiß jedoch, dass die Kosten, die nicht anfallen, Gemeinkosten verursachen.

Grant Fritchey
quelle
Vielen Dank, Grant, dass du es versucht hast. Du bist mit allem, was ich mir ausgedacht habe, viel näher gekommen als ich.
SpaceGhost440
2

Grant, ich glaube ein Mitarbeiter (Dennis Rogers) und ich habe die Frage beantwortet. Hier erscheint die endgültige Formel, mit der SSMS die Betreiberkosten und die Kosten in% berechnet.

Geschätzte Betreiberkosten == @EstimatedTotalSubtreeCost - Summe (unmittelbare Kinder @ EstimatedTotalSubtreeCost)

Geschätzter Betreiberkostenprozentsatz = Geschätzte Betreiberkosten / StmtSimple @ StatementSubTreeCost * 100

Ich habe dies mit mehreren Plänen getestet und dies scheint genau richtig zu sein.

Um die obige Berechnung als xpath darzustellen, wird daraus:

@EstimatedTotalSubtreeCost - sum(./descendant::s:RelOp[1]/../s:RelOp/@EstimatedTotalSubtreeCost) 

Die Summe findet den ersten Nachkommen vom Typ RelOp, sichert dann eine Ebene und ruft alle RelOps auf dieser Ebene ab und extrahiert ihre EstimatedTotalSubtreeCost.

SpaceGhost440
quelle