একটি এক্সএমএল সূচক সহ খুব অদ্ভুত অভিনয়


32

আমার প্রশ্নটি এর উপর ভিত্তি করে: 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 !!!

উত্তর:


33

এখানে অনেক কিছু চলছে তা নিশ্চিত তাই আমাদের কেবল কোথায় এটি বাড়ে তা দেখতে হবে।

প্রথমত, এসকিউএল সার্ভার ২০১২ এবং এসকিউএল সার্ভার ২০১৪-এর মধ্যে সময়ের পার্থক্যটি এসকিউএল সার্ভার ২০১৪-এ নতুন কার্ডিনালিটি অনুমানকারীর কারণে the এসকিউএল সার্ভার ২০১২-এর মতো এসকিউএল সার্ভার ২০১৪-তে বৈশিষ্ট্যগুলি।

nodes()বনাম তুলনা exist()করা মোটেও ন্যায়সঙ্গত নয় কারণ যদি এক সারিতে XML এ একাধিক ম্যাচিং উপাদান থাকে তবে তারা একই ফলাফলটি ফিরিয়ে দেবে না। exist()বেস টেবিল থেকে নির্বিশেষে এক সারি ফিরে আসবে, যেখানে nodes()সম্ভাব্যভাবে বেস টেবিলের প্রতিটি সারিটির জন্য আপনাকে একাধিক সারি ফেরত দিতে পারে।
আমরা ডেটা জানি তবে এসকিউএল সার্ভারটি একটি কোয়েরি পরিকল্পনা তৈরি করে না এবং তা বিবেচনায় নিয়ে আসে।

করতে nodes()করার জন্য query সমতুল্য exist()ক্যোয়ারী, আপনি ভালো কিছু করতে পারে।

SELECT testTbl.*
FROM testTbl
WHERE EXISTS (
             SELECT *
             FROM XmlColumn.nodes('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') AS a(b)
             )

এই জাতীয় একটি কোয়েরির সাথে ব্যবহার করার nodes()বা তার মধ্যে কোনও পার্থক্য নেই exist()কারণ এসকিউএল সার্ভার দুটি সংস্করণ সূচক ব্যবহার না করে এবং সূচক ব্যবহার করার সময় ঠিক একই পরিকল্পনা তৈরি করে almost এটি এসকিউএল সার্ভার 2012 এবং এসকিউএল সার্ভার 2014 এর ক্ষেত্রেই সত্য true

এসকিউএল সার্ভার ২০১২-এ আমার জন্য এক্সএমএল সূচি ব্যতীত nodes()প্রশ্নের উপরের ক্যোয়ারীর পরিবর্তিত সংস্করণ ব্যবহার করে seconds সেকেন্ড সময় লাগবে । পূর্ণ পথ বা সংক্ষিপ্ত পথ ব্যবহারের মধ্যে কোনও পার্থক্য নেই। এক্সএমএল সূচকের জায়গায় পুরো পাথ সংস্করণটি সবচেয়ে দ্রুত এবং 5 এমএস লাগে এবং সংক্ষিপ্ত পথটি ব্যবহার করে প্রায় 500 এমএস লাগে। কোয়েরি পরিকল্পনাগুলি পরীক্ষা করা আপনাকে বলবে কেন পার্থক্য রয়েছে তবে সংক্ষিপ্ত সংস্করণটি হ'ল আপনি যখন একটি সংক্ষিপ্ত পথ ব্যবহার করেন তখন এসকিউএল সার্ভার সূচীতে স্বল্প পথের সন্ধান করে (ব্যবহারের সীমাটি চেষ্টা করেlike ) এবং সারিগুলি ছাড়ার আগে 700000 সারি ফেরত দেয় যা মান মেলে না। পুরো পাথটি ব্যবহার করার সময়, এসকিউএল সার্ভারটি অনুসন্ধানের জন্য নোডের মানের সাথে সরাসরি অভিব্যক্তিটি প্রকাশ করতে পারে এবং স্ক্র্যাচ থেকে কেবল 105 টি সারি কাজ করতে দেয় returns

এসকিউএল সার্ভার ২০১৪ এবং নতুন কার্ডিনালটি অনুমানকারী ব্যবহার করে, এক্সএমএল সূচক ব্যবহার করার সময় এই প্রশ্নের মধ্যে কোনও পার্থক্য নেই। সূচকটি ব্যবহার না করে প্রশ্নগুলি এখনও একই পরিমাণে সময় নেয় তবে এটি 15 সেকেন্ড। স্পষ্টতই এখানে নতুন স্টাফ ব্যবহার করার সময় কোনও উন্নতি হবে না।

নিশ্চিত না যে আমি আপনার প্রশ্নটি আসলে কী সে সম্পর্কে পুরোপুরি হারিয়ে ফেলেছি যেহেতু আমি প্রশ্নের সমতুল্য হওয়ার জন্য পরিবর্তন করেছি তবে এখানে আমি বিশ্বাস করি এটি এখন is

কেন nodes()কোনও এক্সএমএল সূচক সহ কোয়েরি (মূল সংস্করণ) উল্লেখযোগ্যভাবে ধীর হয় তখন যখন কোনও সূচক ব্যবহার করা হয় না?

ঠিক আছে, উত্তরটি হ'ল এসকিউএল সার্ভার ক্যোয়ারী প্ল্যান অপ্টিমাইজারটি কিছু খারাপ কাজ করে এবং এটি একটি স্পুল অপারেটরটি প্রবর্তন করে। কেন জানি না তবে সুসংবাদটি হ'ল এসকিউএল সার্ভার ২০১৪-এ নতুন কার্ডিনাল্টি অনুমানকারী সহ এটি আর নেই
। সূচকের সাথে এটি পুরানো অনুমানকারী (এসকিউএল সার্ভার ২০১২) এর সাথে 15 সেকেন্ড এবং নতুন অনুমানকারী (এসকিউএল সার্ভার 2014) সহ প্রায় 2 সেকেন্ড সময় নেয়।

দ্রষ্টব্য: উপরের ফলাফলগুলি আপনার পরীক্ষার ডেটা সহ বৈধ। আপনি এক্সএমএলের আকার, আকৃতি বা ফর্মটি পরিবর্তন করেন কিনা তা বলার জন্য সম্পূর্ণ আলাদা গল্প থাকতে পারে। টেবিলগুলিতে আপনার কাছে থাকা ডেটাটি পরীক্ষা না করে নিশ্চিতভাবে জানার কোনও উপায় নেই।

এক্সএমএল সূচকগুলি কীভাবে কাজ করে

এসকিউএল সার্ভারে এক্সএমএল সূচকগুলি অভ্যন্তরীণ সারণী হিসাবে প্রয়োগ করা হয়। প্রাথমিক এক্সএমএল সূচকটি মোট 12 কলামে বেস টেবিল প্লাস নোড আইডি কলামের প্রাথমিক কী সহ সারণী তৈরি করে। এটিতে প্রতি এক সারি থাকবে element/node/attribute etc.যাতে সারণী অবশ্যই XML আকারের আকারের উপর নির্ভর করে সত্যিই বড় হতে পারে। জায়গায় প্রাথমিক XML সূচক সহ এসকিউএল সার্ভারটি বেস টেবিলের প্রতিটি সারির জন্য এক্সএমএল নোড এবং মানগুলি সনাক্ত করতে অভ্যন্তরীণ সারণীর প্রাথমিক কীটি ব্যবহার করতে পারে।

মাধ্যমিক এক্সএমএল সূচকগুলি তিন প্রকারে আসে। আপনি যখন একটি গৌণ এক্সএমএল সূচক তৈরি করেন, অভ্যন্তরীণ টেবিলের উপরে একটি নন-ক্লাস্টারড সূচক তৈরি হয় এবং আপনি কী ধরণের গৌণ সূচক তৈরি করেন তার উপর নির্ভর করে এর বিভিন্ন কলাম এবং কলামের আদেশ থাকবে।

থেকে এক্সএমএল এর INDEX (লেনদেন এসকিউএল) তৈরি :

VALUE
কলামগুলিতে গৌণ XML সূচক তৈরি করে যেখানে মূল কলামগুলি প্রাথমিক এক্সএমএল সূচকের (নোড মান এবং পথ) হয়।

PATH
প্রাথমিক এক্সএমএল সূচীতে পাথ মান এবং নোড মানগুলিতে নির্মিত কলামগুলিতে একটি গৌণ এক্সএমএল সূচক তৈরি করে। PATH মাধ্যমিক সূচকগুলিতে, পাথ এবং নোডের মানগুলি হ'ল মূল কলামগুলি যেগুলি পাথ অনুসন্ধান করার সময় দক্ষ সন্ধানের অনুমতি দেয়।

সম্পত্তি
প্রাথমিক এক্সএমএল সূচকের কলামগুলিতে (পিকে, পাথ এবং নোড মান) একটি গৌণ এক্সএমএল সূচক তৈরি করে যেখানে পিকে বেস টেবিলের প্রাথমিক কী।

সুতরাং আপনি যখন একটি PATH সূচক তৈরি করবেন, সেই সূচকের প্রথম কলামটি হল পথ প্রকাশ এবং দ্বিতীয় কলামটি সেই নোডের মান। প্রকৃতপক্ষে, পথটি এক ধরণের সংকোচিত বিন্যাসে সঞ্চয় করা হয় এবং বিপরীত হয়। এটি বিপরীতভাবে সঞ্চিত রয়েছে যা সংক্ষিপ্ত পথের এক্সপ্রেশন ব্যবহার করে অনুসন্ধানগুলিতে এটি দরকারী করে। আপনার সংক্ষিপ্ত পথ যদি আপনি অনুসন্ধান //item/value/@string, //item/@nameএবং //item। যেহেতু পাথটি কলামে বিপরীতভাবে সঞ্চিত রয়েছে তাই এসকিউএল সার্ভারটি like = '€€€€€€%যেখানে €€€€€€পথটি বিপরীত হয়েছে তা সন্ধান করে একটি সীমা ব্যবহার করতে পারে । আপনি যখন একটি পূর্ণ পথ ব্যবহার করেন, ব্যবহার করার কোনও কারণ নেই কারণ likeপুরো পথটি কলামে এনকোড করা হয়েছে এবং মানটি প্রিকিকেটটিতেও ব্যবহার করা যেতে পারে।

আপনার প্রশ্নসমূহ :

কখন একটি এক্সএমএল সূচক তৈরি করা উচিত?

সর্বশেষ উপায় হিসাবে যদি কখনও হয়। আপনার ডাটাবেসটি ডিজাইন করা আরও ভাল যাতে আপনাকে কোনও ক্লমের ক্ষেত্রে ফিল্টার করার জন্য এক্সএমএল এর ভিতরে মানগুলি ব্যবহার করতে হবে না। আপনি যদি এটি আগেই জানেন যে আপনার এটি করা দরকার, আপনি প্রয়োজনের ভিত্তিতে সূচিপত্র করতে পারেন এমন একটি গণিত কলাম তৈরি করতে আপনি সম্পত্তি প্রচার ব্যবহার করতে পারেন। এসকিউএল সার্ভার ২০১২ এসপি 1, আপনার কাছে বেছে বেছে এক্সএমএল সূচকগুলিও উপলব্ধ। দৃশ্যের পিছনে কাজগুলি নিয়মিত এক্সএমএল সূচকগুলির মতো একই, কেবলমাত্র আপনি সূচী সংজ্ঞায় পথের অভিব্যক্তিটি নির্দিষ্ট করেন এবং কেবল যে নোডগুলি মেলে তা সূচিযুক্ত হয়। এইভাবে আপনি অনেক জায়গা বাঁচাতে পারবেন।

সূচকের সাথে .nodes () কেন আরও খারাপ হতে পারে?

যখন কোনও টেবিলে একটি এক্সএমএল সূচক তৈরি করা হয়, এসকিউএল সার্ভার সর্বদা ডেটা পেতে সেই সূচকটি (অভ্যন্তরীণ সারণী) ব্যবহার করবে। কোনটি দ্রুত এবং কোনটি দ্রুত নয় তার বিষয়ে অপ্টিমাইজারের বক্তব্য দেওয়ার আগে এই সিদ্ধান্ত নেওয়া হয়। অপ্টিমাইজারটিতে ইনপুট পুনর্লিখন করা হয়েছে তাই এটি অভ্যন্তরীণ সারণীগুলি ব্যবহার করছে এবং এর পরে এটি নিয়মিত ক্যোয়ারির মতো সেরাটি করার জন্য অপ্টিমাইজারের উপর নির্ভর করে। যখন কোনও সূচক ব্যবহার করা হয় না, সেখানে কয়েকটি টেবিল-মূল্যযুক্ত ফাংশন থাকে যা পরিবর্তে ব্যবহৃত হয়। নীচের লাইনটি হচ্ছে আপনি পরীক্ষা ছাড়াই দ্রুত কী হবে তা বলতে পারবেন না।

কেউ কীভাবে নেতিবাচক প্রভাব এড়াতে পারে?

পরীক্ষামূলক


2
পার্থক্য সম্পর্কে আপনার ধারণা .nodes()এবং .exist()বিশ্বাসযোগ্য। এছাড়াও সূচকটি যে full path searchদ্রুত তা বোঝা সহজ মনে হয়। এই অর্থ হবে: আপনি একটি XML সূচক তৈরি করেন তবে আপনার উচিত সবসময় কোন জেনেরিক জন্য XPath (সঙ্গে নেতিবাচক প্রভাব সচেতন হতে //বা *বা ..বা [filter]বা কিছু শুধু সাধারণ Xpath ...)। আসলে আপনার পুরো পথটিই ব্যবহার করা উচিত - বেশ দুর্দান্ত ব্যাক ড্র ...
শ্নুগো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.