私の質問はこれに基づいています:https : //stackoverflow.com/q/35575990/5089204
そこで答えを出すために、次のテストシナリオを行いました。
テストシナリオ
最初にテストテーブルを作成し、100.000行を入力します。乱数(0から1000)は、乱数ごとに最大100行になるはずです。この番号はvarchar colに入れられ、XMLの値として使用されます。
次に、OPのような呼び出しを行います。.exist()および.nodes()を使用して、2番目の利点はわずかですが、両方とも5〜6秒かかります。実際に、呼び出しを2回行います。2回目はスワップされた順序で、検索パラメーターをわずかに変更し、フルパスではなく「// item」を使用して、キャッシュされた結果またはプランによる誤検知を回避します。
次に、XMLインデックスを作成し、同じ呼び出しを行います
今-本当に驚いたことは何ですか!- .nodes
との完全なパスがはるかに遅い(9秒)前よりもなく.exist()
して、半秒までであるフルパスもダウン約0.10秒です。(一方.nodes()
、短いパスの方が優れていますが、それでもはるかに遅れています.exist()
)
質問:
私自身のテストをまとめると、XMLインデックスはデータベースを極端に破壊する可能性があります。それらは物事を非常に高速化できますが(s。edit 2)、クエリも遅くなります。それらがどのように機能するかを理解したいのですが... XMLインデックスを作成する必要があるのはいつですか?.nodes()
インデックスを使用すると、インデックスを使用しない場合よりも悪くなるのはなぜですか?否定的な影響をどのように回避できますか?
CREATE TABLE #testTbl(ID INT IDENTITY PRIMARY KEY, SomeData VARCHAR(100),XmlColumn XML);
GO
DECLARE @RndNumber VARCHAR(100)=(SELECT CAST(CAST(RAND()*1000 AS INT) AS VARCHAR(100)));
INSERT INTO #testTbl VALUES('Data_' + @RndNumber,
'<error application="application" host="host" type="exception" message="message" >
<serverVariables>
<item name="name1">
<value string="text" />
</item>
<item name="name2">
<value string="text2" />
</item>
<item name="name3">
<value string="text3" />
</item>
<item name="name4">
<value string="text4" />
</item>
<item name="name5">
<value string="My test ' + @RndNumber + '" />
</item>
<item name="name6">
<value string="text6" />
</item>
<item name="name7">
<value string="text7" />
</item>
</serverVariables>
</error>');
GO 100000
DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesFullPath_no_index;
GO
DECLARE @d DATETIME=GETDATE();
SELECT *
FROM #testTbl
WHERE XmlColumn.exist('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistFullPath_no_index;
GO
DECLARE @d DATETIME=GETDATE();
SELECT *
FROM #testTbl
WHERE XmlColumn.exist('//item[@name="name5" and value/@string="My test 500"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistShortPath_no_index;
GO
DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('//item[@name="name5" and value/@string="My test 500"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesShortPath_no_index;
GO
CREATE PRIMARY XML INDEX PXML_test_XmlColum1 ON #testTbl(XmlColumn);
CREATE XML INDEX IXML_test_XmlColumn2 ON #testTbl(XmlColumn) USING XML INDEX PXML_test_XmlColum1 FOR PATH;
GO
DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesFullPath_with_index;
GO
DECLARE @d DATETIME=GETDATE();
SELECT *
FROM #testTbl
WHERE XmlColumn.exist('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistFullPath_with_index;
GO
DECLARE @d DATETIME=GETDATE();
SELECT *
FROM #testTbl
WHERE XmlColumn.exist('//item[@name="name5" and value/@string="My test 500"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistShortPath_with_index;
GO
DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('//item[@name="name5" and value/@string="My test 500"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesShortPath_with_index;
GO
DROP TABLE #testTbl;
編集1-結果
これは、中規模のラップトップにローカルにインストールされたSQL Server 2012の結果の1つです。このテストNodesFullPath_with_index
では、インデックスがない場合よりも遅いものの、非常に否定的な影響を再現できませんでした...
NodesFullPath_no_index 6.067
ExistFullPath_no_index 6.223
ExistShortPath_no_index 8.373
NodesShortPath_no_index 6.733
NodesFullPath_with_index 7.247
ExistFullPath_with_index 0.217
ExistShortPath_with_index 0.500
NodesShortPath_with_index 2.410
より大きなXMLでのEDIT 2テスト
TTの提案によると、上記のXMLを使用しましたが、item
-nodesをコピーして約450個のアイテムに到達しました。ヒットノードをXML内で非常に高くしました(.exist()
最初のヒットで停止するが、.nodes()
続行すると思うので)
XML-indexを作成するとmdf-fileが〜21GBに爆発し、〜18GBはインデックスに属しているようです(!!!)
NodesFullPath_no_index 3min44
ExistFullPath_no_index 3min39
ExistShortPath_no_index 3min49
NodesShortPath_no_index 4min00
NodesFullPath_with_index 8min20
ExistFullPath_with_index 8,5 seconds !!!
ExistShortPath_with_index 1min21
NodesShortPath_with_index 13min41 !!!
.nodes()
との違いについてのあなたのアイデア.exist()
は説得力があります。また、インデックスfull path search
が速いという事実は理解しやすいようです。これが意味するだろう:あなたはXMLインデックスを作成する場合は、あなたがしなければならない、常に任意の汎用のXPath(負の影響を意識する//
か、*
または..
または[filter]
または何もない単なるXpathは...)。実際には、フルパスのみを使用する必要があります-非常に素晴らしいバックドロー