আমার প্রশ্নটি এর উপর ভিত্তি করে: https://stackoverflow.com/q/35575990/5089204
সেখানে একটি উত্তর দিতে আমি নিম্নলিখিত পরীক্ষার-দৃশ্যটি করেছি।
পরীক্ষার দৃশ্য
প্রথমে আমি একটি পরীক্ষার টেবিল তৈরি করি এবং এটি 100.000 সারি দিয়ে পূরণ করি। একটি এলোমেলো সংখ্যা (0 থেকে 1000) প্রতিটি এলোমেলো সংখ্যার জন্য 100 ডলার সারি করে। এই নম্বরটি একটি ভার্চার কোলে এবং আপনার এক্সএমএলে একটি মান হিসাবে দেওয়া হয়।
তারপরে আমি ওপি'র মতো একটি কল করি istএক্সিস্ট () এবং। নোড () সহ দ্বিতীয়টির জন্য একটি ছোট সুবিধা সহ এটির প্রয়োজন, তবে উভয়ই 5 থেকে 6 সেকেন্ড সময় নেয়। প্রকৃতপক্ষে আমি দু'বার কলগুলি করেছি: দ্বিতীয় বার অদলবদল ক্রমে এবং কিছুটা পরিবর্তিত অনুসন্ধান প্যারাম এবং "ক্যাটাগড ফলাফল বা পরিকল্পনার মাধ্যমে মিথ্যা ইতিবাচকতা এড়ানোর জন্য পুরো পথের পরিবর্তে" // আইটেম "দিয়ে।
তারপরে আমি একটি এক্সএমএল সূচক তৈরি করি এবং একই কলগুলি করি
এখন - সত্যিই কি আমাকে অবাক করেছে! - পূর্ণ পাথ.nodes
সহ পূর্বের তুলনায় অনেক ধীর গতি (9 সেকেন্ড) তবে এটি আধা সেকেন্ডে নেমে গেছে, পুরো পাথ এমনকি প্রায় 0.10 সেকেন্ড পর্যন্ত রয়েছে। (একই সঙ্গে সংক্ষিপ্ত পাথ উত্তম, কিন্তু এখনও পর্যন্ত পিছনে.exist()
.nodes()
.exist()
)
প্রশ্নাবলী:
আমার নিজের পরীক্ষাগুলি সংক্ষেপে নিয়ে আসে: এক্সএমএল সূচকগুলি একটি ডেটাবেসকে চূড়ান্তভাবে ফুটিয়ে তুলতে পারে। তারা জিনিসগুলিকে অত্যন্ত গতিময় করতে পারে (গুলি 2 সম্পাদনা করুন), তবে আপনার অনুসন্ধানগুলিও কমিয়ে দিতে পারে। আমি বুঝতে পারি যে তারা কীভাবে কাজ করে ... একটি এক্সএমএল সূচক কখন তৈরি করা উচিত? কেন .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 - ফলাফল
এটি একটি এসকিউএল সার্ভার ২০১২ এর সাথে একটি ফলাফল যা স্থানীয়ভাবে একটি মিডিয়াম ল্যাপটপে ইনস্টল করা হয় এই পরীক্ষায় আমি চূড়ান্ত নেতিবাচক প্রভাবের উপর পুনরুত্পাদন করতে পারিনি 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
বড় এক্সএমএল সহ 2 টি সম্পাদনা সম্পাদনা করুন
item
টিটির পরামর্শ অনুযায়ী আমি উপরের এক্সএমএল ব্যবহার করেছি, তবে নোডগুলি অনুলিপি করে প্রায় 450 টি আইটেম পৌঁছাতে চাই। আমি এক্সএমএলে হিট-নোডটি খুব উপরে উঠতে দিয়েছি ('কারণ আমি মনে করি যে .exist()
এটি প্রথম হিটটি থামবে, যখন .nodes()
চালিয়ে যাবে))
এক্সএমএল-সূচক তৈরি করে এমডিএফ-ফাইলটি 21 গিগাবাইট ডলারে উড়িয়ে দেওয়া হয়েছে, ~ 18 গিগাবাইট সূচকের (!!!) বলে মনে হচ্ছে
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 ...)। আসলে আপনার পুরো পথটিই ব্যবহার করা উচিত - বেশ দুর্দান্ত ব্যাক ড্র ...