1

ここで、TSQL ステートメントが XML データ型の .value または .exist メソッドを使用して XML データをフィルター処理する SO に関するいくつかの応答を見てきました ( hereおよびhere )。私はこれらのメソッドの構築/構文に精通していませんが、より深い問題があります。

キャッシュされた実行計画データに対してクエリを実行し、データ内で特定のインデックスへの参照を検索しようとしていますが、XML のどこを参照すればよいかわからないという問題があります。現在、XML を NVARCHAR にキャストし、LIKE を使用しています (クエリの最後の行を参照)。

  DECLARE @IndexName NVARCHAR(100) = 'MyIndex'

    SELECT  OBJECT_NAME(objectid) AS procname, usecounts, query_plan
    FROM    sys.dm_exec_cached_plans cp
    CROSS   APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
    WHERE   objtype = 'Proc'
    AND     CAST(query_plan AS NVARCHAR(MAX)) LIKE '%' + @IndexName + '%'

したがって、これは機能しますが、余分な結果が得られます。最終的には、インデックスのシークとスキャンの結果を取得したいと考えていますが、現在、インデックスが変更された行も表示されます (インデックスも更新されるため、一般的なテーブル更新の実行計画など)。

  1. ある種のワイルドカード XML 構文を使用するようにクエリの最後の行を言い換える (そしてキャストを避ける) にはどうすればよいですか?
  2. 「IndexScan」の親ノードを持つアイテムのみを返すようにそのクエリを絞り込むにはどうすればよいですか
  3. 「RelOp」の最初に見つかった先祖が「Index Seek」の値を持つ「PhysicialOp」という名前の属性を持つアイテムのみを返すように、そのクエリを改良するにはどうすればよいですか?

簡単なサンプル XML を次に示します。

<RelOp NodeId="13" PhysicalOp="Index Seek" LogicalOp="Index Seek">
    <OutputList>
        <ColumnReference Database="[MyDB]" Schema="[dbo]" Table="[Employees]" Column="EmployeeID" />
    </OutputList>
    <IndexScan Ordered="1" ScanDirection="FORWARD">
        <DefinedValues>
            <DefinedValue>
                <ColumnReference Database="[MyDB]" Table="[Employees]" Column="EmployeeID" />
            </DefinedValue>
        </DefinedValues>
        <Object Database="[MyDB]" Schema="[dbo]" Table="[Employees]" Index="[MyIndex]" />
    </IndexScan>
</RelOp>
4

1 に答える 1

6
declare @IndexName nvarchar(100) = '[MyIndex]';

with xmlnamespaces (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
select object_name(qp.objectid), 
       cp.usecounts,
       qp.query_plan
from sys.dm_exec_cached_plans as cp
  cross apply sys.dm_exec_query_plan(cp.plan_handle) as qp
where cp.objtype = 'Proc' and
      qp.query_plan.exist('//RelOp[
                                  @PhysicalOp = "Index Seek" and 
                                  IndexScan/Object/@Index = sql:variable("@IndexName")
                                  ]') = 1;

クエリ プランのインデックスには角かっこがあるため、変数にそれを含める必要があります。

//RelOpは、変数に保存した子ノードが存在する場所を選択して、すべてのRelOpノードを詳細に検索します。@PhysicalOpIndex SeekIndexScan/Object@Index

于 2013-07-10T14:15:48.997 に答える