読者です 読者をやめる 読者になる 読者になる

実行プランを グラフィカルに見たい

今から実行するクエリの実行プランが欲しい - お だ のスペース で実行プランを取りました。
SSMS(SQL Server Management Studio) だと図で見れますが、実行プランは単なる XML です。
自前のアプリで似たような感じに出来ないかなーということで探してみました。
html-query-plan - A tool for displaying SQL query execution plans as HTML - Google Project Hosting
こちらを使って実行プランを図で見てみましょう。
こんな実行プランが

<?xml version=""1.0"" encoding=""utf-16""?>
<ShowPlanXML xmlns=""http://schemas.microsoft.com/sqlserver/2004/07/showplan"" Version=""1.2"" Build=""11.0.3128.0"">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementText=""select * from 受注 where 受注ID = 1&#xD;"" StatementId=""1"" StatementCompId=""1"" StatementType=""SELECT"" RetrievedFromCache=""false"" StatementSubTreeCost=""0.339657"" StatementEstRows=""1"" StatementOptmLevel=""FULL"" QueryHash=""0xC13D8783D17B32A6"" QueryPlanHash=""0x8AA6A72839D29830"" StatementOptmEarlyAbortReason=""GoodEnoughPlanFound"" ParameterizedText=""(@1 tinyint)SELECT * FROM [受注] WHERE [受注ID]=@1"">
          <StatementSetOptions QUOTED_IDENTIFIER=""true"" ARITHABORT=""true"" CONCAT_NULL_YIELDS_NULL=""true"" ANSI_NULLS=""true"" ANSI_PADDING=""true"" ANSI_WARNINGS=""true"" NUMERIC_ROUNDABORT=""false"" />
          <QueryPlan CachedPlanSize=""24"" CompileTime=""4"" CompileCPU=""4"" CompileMemory=""216"">
            <Warnings>
              <PlanAffectingConvert ConvertIssue=""Cardinality Estimate"" Expression=""CONVERT_IMPLICIT(int,[sqlworld].[dbo].[受注].[受注ID],0)"" />
              <PlanAffectingConvert ConvertIssue=""Seek Plan"" Expression=""CONVERT_IMPLICIT(int,[sqlworld].[dbo].[受注].[受注ID],0)=CONVERT_IMPLICIT(int,[@1],0)"" />
              <PlanAffectingConvert ConvertIssue=""Seek Plan"" Expression=""CONVERT_IMPLICIT(int,[sqlworld].[dbo].[受注].[受注ID],0)=(1)"" />
            </Warnings>
            <MemoryGrantInfo SerialRequiredMemory=""0"" SerialDesiredMemory=""0"" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant=""207559"" EstimatedPagesCached=""51889"" EstimatedAvailableDegreeOfParallelism=""2"" />
            <RelOp NodeId=""1"" PhysicalOp=""Nested Loops"" LogicalOp=""Inner Join"" EstimateRows=""1"" EstimateIO=""0"" EstimateCPU=""4.18e-006"" AvgRowSize=""32"" EstimatedTotalSubtreeCost=""0.339657"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row"">
              <OutputList>
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注日"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""得意先コード"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""営業担当者コード"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注コード"" />
              </OutputList>
              <NestedLoops Optimized=""0"">
                <OuterReferences>
                  <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                </OuterReferences>
                <RelOp NodeId=""2"" PhysicalOp=""Index Scan"" LogicalOp=""Index Scan"" EstimateRows=""1"" EstimateIO=""0.16831"" EstimateCPU=""0.110093"" AvgRowSize=""19"" EstimatedTotalSubtreeCost=""0.278403"" TableCardinality=""99942"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row"">
                  <OutputList>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注コード"" />
                  </OutputList>
                  <IndexScan Ordered=""0"" ForcedIndex=""0"" ForceSeek=""0"" ForceScan=""0"" NoExpandHint=""0"" Storage=""RowStore"">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注コード"" />
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Index=""[IX_受注]"" IndexKind=""NonClustered"" />
                    <Predicate>
                      <ScalarOperator ScalarString=""CONVERT_IMPLICIT(int,[sqlworld].[dbo].[受注].[受注ID],0)=(1)"">
                        <Compare CompareOp=""EQ"">
                          <ScalarOperator>
                            <Convert DataType=""int"" Style=""0"" Implicit=""1"">
                              <ScalarOperator>
                                <Identifier>
                                  <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                                </Identifier>
                              </ScalarOperator>
                            </Convert>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Const ConstValue=""(1)"" />
                          </ScalarOperator>
                        </Compare>
                      </ScalarOperator>
                    </Predicate>
                  </IndexScan>
                </RelOp>
                <RelOp NodeId=""4"" PhysicalOp=""Clustered Index Seek"" LogicalOp=""Clustered Index Seek"" EstimateRows=""1"" EstimateIO=""0.003125"" EstimateCPU=""0.0001581"" AvgRowSize=""20"" EstimatedTotalSubtreeCost=""0.0032831"" TableCardinality=""99942"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row"">
                  <OutputList>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注日"" />
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""得意先コード"" />
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""営業担当者コード"" />
                  </OutputList>
                  <IndexScan Lookup=""1"" Ordered=""1"" ScanDirection=""FORWARD"" ForcedIndex=""0"" ForceSeek=""0"" ForceScan=""0"" NoExpandHint=""0"" Storage=""RowStore"">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注日"" />
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""得意先コード"" />
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""営業担当者コード"" />
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Index=""[PK_受注]"" TableReferenceId=""-1"" IndexKind=""Clustered"" />
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <Prefix ScanType=""EQ"">
                            <RangeColumns>
                              <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString=""[sqlworld].[dbo].[受注].[受注ID]"">
                                <Identifier>
                                  <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </Prefix>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                  </IndexScan>
                </RelOp>
              </NestedLoops>
            </RelOp>
            <ParameterList>
              <ColumnReference Column=""@1"" ParameterCompiledValue=""(1)"" />
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
        <StmtSimple StatementText=""&#xA;select * from 受注"" StatementId=""2"" StatementCompId=""2"" StatementType=""SELECT"" RetrievedFromCache=""false"" StatementSubTreeCost=""0.425811"" StatementEstRows=""99942"" StatementOptmLevel=""TRIVIAL"" QueryHash=""0x7345CF21F440D0AF"" QueryPlanHash=""0xAB9999324F75BFA8"">
          <StatementSetOptions QUOTED_IDENTIFIER=""true"" ARITHABORT=""true"" CONCAT_NULL_YIELDS_NULL=""true"" ANSI_NULLS=""true"" ANSI_PADDING=""true"" ANSI_WARNINGS=""true"" NUMERIC_ROUNDABORT=""false"" />
          <QueryPlan CachedPlanSize=""8"" CompileTime=""0"" CompileCPU=""0"" CompileMemory=""80"">
            <MemoryGrantInfo SerialRequiredMemory=""0"" SerialDesiredMemory=""0"" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant=""207559"" EstimatedPagesCached=""51889"" EstimatedAvailableDegreeOfParallelism=""2"" />
            <RelOp NodeId=""0"" PhysicalOp=""Clustered Index Scan"" LogicalOp=""Clustered Index Scan"" EstimateRows=""99942"" EstimateIO=""0.315718"" EstimateCPU=""0.110093"" AvgRowSize=""32"" EstimatedTotalSubtreeCost=""0.425811"" TableCardinality=""99942"" Parallel=""0"" EstimateRebinds=""0"" EstimateRewinds=""0"" EstimatedExecutionMode=""Row"">
              <OutputList>
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注日"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""得意先コード"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""営業担当者コード"" />
                <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注コード"" />
              </OutputList>
              <IndexScan Ordered=""0"" ForcedIndex=""0"" ForceScan=""0"" NoExpandHint=""0"">
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注ID"" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注日"" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""得意先コード"" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""営業担当者コード"" />
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Column=""受注コード"" />
                  </DefinedValue>
                </DefinedValues>
                <Object Database=""[sqlworld]"" Schema=""[dbo]"" Table=""[受注]"" Index=""[PK_受注]"" IndexKind=""Clustered"" />
              </IndexScan>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

このように表示されます。

マウスカーソルを乗せると…

これはかなり良いのではないでしょうか!
という訳で、XML の実行プランを Upload すると図で表示してくれるサイトを用意 Azure Web Site で立ててみました。
実行プラン表示 - マイ ASP.NET アプリケーション
実行プランファイルを Upload すると、その内容を表示します。