sql >> データベース >  >> Database Tools >> SSMS

[実際の実行プランを含める]を使用してプログラムでクエリを実行し、インデックスの提案があるかどうかを確認する方法はありますか?

    まず、コードで実際の実行プランを取得し、インデックスが必要であると報告するプランを見つける方法に入る前に、データベースエンジンチューニングアドバイザー(DTA) 、すべてのクエリのリストをフィードすると、それらが処理され、可能なインデックス、統計、およびクエリの計画に役立つその他の多くのことが通知されます。

    100万以上のクエリのリストを提供するよりも、実行中の実際のクエリを含むトレースをサーバーから取得でき、最も時間がかかっているクエリに焦点を当てることができます。

    元の質問に答えるには、SET STATISTICS XML ONを追加する必要があります 接続の開始時に、これにより、表示したGUIが基づいているXMLデータが提供されます。 (取得の詳細については、こちらをご覧ください計画 )。これを行うと、クエリは最初の列の最初の行にプランのxmlを含む追加の結果セットとともに返されます。

    これは、それを行う迅速で汚い関数です。

    private static string GetXmlPlanForQuery(string queryText)
    {
        string result = null;
        using (var connection = new SqlConnection(connectionString))
        using (var command = new SqlCommand())
        {
            connection.Open();
            command.Connection = connection;
    
            //Enable the statistics.
            command.CommandText = "SET STATISTICS XML ON";
            command.ExecuteNonQuery();
    
            //Run through the query, keeping the first row first column of the last result set.
            command.CommandText = queryText;
            using (var reader = command.ExecuteReader())
            {
                object lastValue = null;
                do
                {
                    if (reader.Read())
                    {
                        lastValue = reader.GetValue(0);
                    }
                } while (reader.NextResult());
    
                if (lastValue != null)
                {
                    result = lastValue as string;
                }
            }
        }
        return result;
    }
    

    そして、これがクエリselect TOTAL_SALES from clients where ACTIVE = 0;に対して返されたXMLです。 ローカルデータベースの1つで実行したこと。

    <?xml version="1.0"?>
    <ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.2" Build="11.0.5058.0">
      <BatchSequence>
        <Batch>
          <Statements>
            <StmtSimple StatementText="SELECT [TOTAL_SALES] FROM [clients] WHERE [ACTIVE][email protected]" StatementId="1" StatementCompId="1" StatementType="SELECT" RetrievedFromCache="false" StatementSubTreeCost="0.0767454" StatementEstRows="315" StatementOptmLevel="FULL" QueryHash="0x708AE72DD31A316" QueryPlanHash="0x214EA79FF76E6771" 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 DegreeOfParallelism="1" CachedPlanSize="16" CompileTime="1" CompileCPU="1" CompileMemory="192">
                <MissingIndexes>
                  <MissingIndexGroup Impact="94.0522">
                    <MissingIndex Database="[exampleDb]" Schema="[dbo]" Table="[CLIENTS]">
                      <ColumnGroup Usage="EQUALITY">
                        <Column Name="[ACTIVE]" ColumnId="15"/>
                      </ColumnGroup>
                      <ColumnGroup Usage="INCLUDE">
                        <Column Name="[TOTAL_SALES]" ColumnId="18"/>
                      </ColumnGroup>
                    </MissingIndex>
                  </MissingIndexGroup>
                </MissingIndexes>
                <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0"/>
                <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="830838" EstimatedPagesCached="207709" EstimatedAvailableDegreeOfParallelism="2"/>
                <RelOp NodeId="0" PhysicalOp="Clustered Index Scan" LogicalOp="Clustered Index Scan" EstimateRows="315" EstimateIO="0.0749769" EstimateCPU="0.0017685" AvgRowSize="16" EstimatedTotalSubtreeCost="0.0767454" TableCardinality="1465" Parallel="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row">
                  <OutputList>
                    <ColumnReference Database="[exampleDb]" Schema="[dbo]" Table="[CLIENTS]" Column="TOTAL_SALES"/>
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="315" ActualEndOfScans="1" ActualExecutions="1"/>
                  </RunTimeInformation>
                  <IndexScan Ordered="0" ForcedIndex="0" ForceScan="0" NoExpandHint="0">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[exampleDb]" Schema="[dbo]" Table="[CLIENTS]" Column="TOTAL_SALES"/>
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[exampleDb]" Schema="[dbo]" Table="[CLIENTS]" Index="[imp_clpk_CLIENTS]" IndexKind="Clustered"/>
                    <Predicate>
                      <ScalarOperator ScalarString="[exampleDb].[dbo].[CLIENTS].[ACTIVE]=(0)">
                        <Compare CompareOp="EQ">
                          <ScalarOperator>
                            <Identifier>
                              <ColumnReference Database="[exampleDb]" Schema="[dbo]" Table="[CLIENTS]" Column="ACTIVE"/>
                            </Identifier>
                          </ScalarOperator>
                          <ScalarOperator>
                            <Const ConstValue="(0)"/>
                          </ScalarOperator>
                        </Compare>
                      </ScalarOperator>
                    </Predicate>
                  </IndexScan>
                </RelOp>
                <ParameterList>
                  <ColumnReference Column="@1" ParameterCompiledValue="(0)" ParameterRuntimeValue="(0)"/>
                </ParameterList>
              </QueryPlan>
            </StmtSimple>
          </Statements>
        </Batch>
      </BatchSequence>
    </ShowPlanXML>
    

    さて、Microsoftは非常に優れているので、XMLにリストされている名前空間に移動します。 実際に.xsdのコピーを取得できます フォーマットのために。次に、開発者のコ​​マンドプロンプトからxsd showplanxml.xsd /classesを実行できます。 showplanxml.csが表示されます XmlSerializerで使用できます 。

    これは、欠落しているインデックスに対してデバッガーブレークを実行する小さなサンプルプログラムです。

    static void Main(string[] args)
    {
        string result = GetXmlPlanForQuery("select TOTAL_SALES from clients where ACTIVE = 0;");
        XmlSerializer ser = new XmlSerializer(typeof(ShowPlanXML));
        var plan = (ShowPlanXML)ser.Deserialize(new StringReader(result));
    
        var missingIndexes =
            plan.BatchSequence.SelectMany(x => x)
                .SelectMany(x => x.Items)
                .OfType<StmtSimpleType>()
                .Select(x => x.QueryPlan)
                .Where(x => x.MissingIndexes != null && x.MissingIndexes.Any());
    
        foreach (var queryPlan in missingIndexes)
        {
            //This will hit for each statement in the query that was missing a index, check queryPlan.MissingIndexes to see the indexes that are missing.
            Debugger.Break();
        }
    
        Console.WriteLine("Done");
        Console.ReadLine();
    }
    

    XmlSerializerを使用してクラスに脱セラル化しましたが、これをXDocumentに簡単にロードしてから、XPathを使用することもできます。 MissingIndexという名前のすべてのノードを検索します 。




    1. SQLコマンドデータベースダイアグラムの追加

    2. phpMyAdminリモートアクセス

    3. MAMPPro-phpMyAdminの問題を更新

    4. phpmyadminからデータをエクスポートしている間、SQLクエリページに戻ります