0

マスター テーブルのトランザクション レコードの情報を持つ履歴テーブルが 1 つあります。このテーブルでは、XML 列を使用してそのトランザクション情報を格納しました。データを含むテーブル構造は次のようになります。

テーブル情報

コンテンツ内の XML データは、以下のように XML として格納されます。

        <Answers>
      <AnswerSet>
        <Answer questionId="ProductCode">S3404</Answer>
        <Answer questionId="ProductName">Parabolic Triple</Answer>
        <Answer questionId="LegacyOptionID" selectedvalue="1389">1389</Answer>
        <Answer questionId="LegacyContentID" selectedvalue="624">624</Answer>
        <Answer questionId="LegacyPageID" selectedvalue="355">355</Answer>
        <Answer questionId="LegacyParentID" selectedvalue="760">760</Answer>
     </AnswerSet>
    </Answers>

すべての行の構造は同じですが、回答ノードのデータが異なります。ProductCode="S3404" で CreatedDate が New のデータを取得したいと考えています。

次のようなクエリを作成しました

select n2.* from nodehistory n2 CROSS APPLY 
n2.content.nodes('Answers/AnswerSet') T(c) WHERE 
c.value('./Answer[@questionId="ProductCode"][1]','varchar(100)') ='J154'

ProductCode にはノード ID ごとに一意のデータがありますが、これは同じノード ID に対して複数の行を返します。これはトランザクション テーブルであるため、同じ XML を複数回格納できるためです。 XML 処理のために時間がかかると思います。

最初の取得のようにできますか

Select Top 1 nodeid from NodeHistory order by CreatedDate desc

次に、XML 部分を検索します。

パフォーマンスを向上させるためのより適切なビューに関するアイデアはありますか?

4

1 に答える 1

0

XML データで他に多くのことをしていない場合、.exist は .value よりも効率的です。これに関しては、BOL に注記があると思います。sql:variable を使用して、これをより一般的にすることもできます。たとえば、次のようになります。

declare @produceCode varchar(20) = 'S3404'

select n2.* 
from nodehistory n2 
    inner join ( select max(id) id from #nodehistory group by nodeId ) maxId ON n2.id = maxId.id
where n2.content.exist('Answers/AnswerSet/Answer[@questionId="ProductCode"][.=sql:variable("@produceCode")]') = 1

サブクエリを使用して、結果セットを nodeId ごとに max(id) に制限しました。要件はわずかに異なる場合がありますが、アイデアは得られます。

パフォーマンスの点では、XML インデックスは SQL/XML クエリを変換できますが、コストがかかります。ストレージには、元のテーブルの 2 ~ 5 倍のサイズが必要になるため、データと比較検討する必要があります。XML インデックスを使用する場合は、PROPERTY インデックスがこのタイプのクエリに役立ちます。

-- create the primary XML index
CREATE PRIMARY XML INDEX xmlidx_nodehistory ON nodehistory(content)
GO

CREATE XML INDEX xmlprpidx_nodehistory ON nodehistory(content)
USING XML INDEX xmlidx_nodehistory FOR PROPERTY
go

declare @produceCode varchar(20) = 'S3404'

select n2.* 
from nodehistory n2 
    inner join ( select max(id) id from nodehistory group by nodeId ) maxId ON n2.id = maxId.id
where n2.content.exist('Answers/AnswerSet/Answer[@questionId="ProductCode"][.=sql:variable("@produceCode")]') = 1

その他の SQL XML パフォーマンス チューニングのアイデアについては、次の優れた記事を参照してください。

SQL Server 2005 での XML データ型のパフォーマンスの最適化

http://msdn.microsoft.com/en-us/library/ms345118.aspx

SQL Server 2005 の XML インデックス

http://msdn.microsoft.com/en-us/library/ms345121(SQL.90).aspx

于 2012-09-10T13:59:30.927 に答える