web-dev-qa-db-ja.com

SQL Server:XPathパフォーマンスによる解析

ユーザーが結果をフィルターしたい特定のデータポイントを選択できるUIがあります。場所、部門などがあります。すべてのオプションを選択したら、ストアドプロシージャに渡すXML文字列を生成します。

そこから、たとえば場所の場合、一時テーブルを作成し、ユーザーが選択したすべての場所をそのテーブルにダンプします。このテーブルを後でデータに結合します。

実行プランを実行すると、フィルターデータを解析している5つほどのクエリのそれぞれに約12%のコストがかかることに気づきました。これは、フィルターするデータを決定するためだけのクエリの60%以上です。

DECLARE @tmLocations TABLE (
    location VARCHAR (100));
BEGIN
    INSERT INTO @tmLocations
    SELECT ParamValues.x1.value('location[1]', 'VARCHAR(200)')
    FROM   @xml.nodes('data/teammateLocations/locations') AS ParamValues(x1);
END

実行にそれほどコストがかからないように、XMLからデータを抽出する別の方法、または上記のようなクエリを改善する方法はありますか?データの設定には、実際のデータのフィルタリングよりもコストがかかり、パフォーマンスが本当に低下します。

4
SBB

実行プランを実行すると、フィルターデータを解析している5つほどのクエリのそれぞれに約12%のコストがかかることに気づきました。これは、フィルターするデータを決定するためだけのクエリの60%以上です。

クエリのコストは、実際の実行プランでも見積もりに基づいています。クエリの実際の効率はわかりません。

推定値は統計に基づいており、それらは古くなり、誤った推定値とコストを与える可能性があります。

XMLクエリの見積もりは常に間違っています。 XML列の統計は生成されず、XMLパラメーターまたは変数の統計も生成されません。

このかなり単純なXMLクエリを見てください。

_declare @X xml;

select 1
from @X.nodes('*') as T(X);
_

推定クエリプラン

enter image description here

SQL Serverは、XMLに10000の要素があると想定し、そこから推測し続けます。 nodes()関数を使用すると、200個が返されると想定されます。その前に、_@X is not null_が推定行数を66に制限しているかどうかをチェックするフィルター演算子があります。純粋な推測であり、XMLに実際にあるデータにまったく影響されません。

クエリが十分かどうかを知るには、期間、読み取り回数、割り当てられたメモリなどを確認する必要があります。推定コストを使用しないでください。個々のクエリのパーセンテージを使用してパフォーマンスを比較しないでください。

Mister Magooがコメントで提案するように、XMLクエリを改善することができます。

_SELECT ParamValues.x1.value('(location/text())[1]', 'VARCHAR(200)')
FROM  @xml.nodes('data/teammateLocations/locations') AS ParamValues(x1);
_

text()ノードを指定しない場合、SQLサーバーは混合コンテンツXMLで機能するプランを生成し、サブノードからのすべてのノード値を連結する必要があります。

4
Mikael Eriksson