সারসংক্ষেপ
প্রধান সমস্যাগুলি হ'ল:
- অপ্টিমাইজারের পরিকল্পনা নির্বাচন মানগুলির একটি সমান বিতরণ গ্রহণ করে।
- উপযুক্ত সূচির অভাবের অর্থ:
- টেবিল স্ক্যান করা একমাত্র বিকল্প।
- যোগসূত্রটি একটি সূচক নেস্টেড লুপগুলিতে যোগদানের পরিবর্তে একটি নিরীহ নেস্টেড লুপস যোগ হয়। একটি নির্লজ্জ যোগদানের জন্য, যোগদানের পূর্বাভাসগুলি জোড়ার অভ্যন্তরীণ দিকটি নীচে নামানোর পরিবর্তে জোড়ায় মূল্যায়ন করা হয়।
বিস্তারিত
দুটি পরিকল্পনা মৌলিকভাবে বেশ সমান, যদিও কার্য সম্পাদন খুব আলাদা হতে পারে:
অতিরিক্ত কলামগুলি নিয়ে পরিকল্পনা করুন
অতিরিক্ত কলামগুলির সাথে এটি নেওয়া যা প্রথমে যুক্তিসঙ্গত সময়ে সম্পূর্ণ হয় না:
আকর্ষণীয় বৈশিষ্ট্যগুলি হ'ল:
- শীর্ষে নোড 0 শীর্ষে সারিগুলি 100 এ ফিরে আসার সীমাবদ্ধ করে It এটি অপ্টিমাইজারের জন্য একটি সারি লক্ষ্যও নির্ধারণ করে, সুতরাং পরিকল্পনার নীচে সমস্ত কিছু প্রথম 100 সারি দ্রুত ফিরিয়ে আনার জন্য বেছে নেওয়া হয়।
- নোড 4-এ স্ক্যানটি সারণি থেকে সারি সন্ধান করে যেখানে
Start_Time
ull State
বা 4 হয় এবং Operation_Type
তালিকাভুক্ত মানগুলির মধ্যে একটি। উল্লিখিত পূর্বাভাসগুলির বিরুদ্ধে প্রতিটি সারিটি পরীক্ষা করে টেবিলে একবার পুরো স্ক্যান করা হয়। কেবলমাত্র সারিগুলি যা সমস্ত পরীক্ষায় উত্তীর্ণ হয় তা বাছাই করে। অপ্টিমাইজারটি অনুমান করে যে 38,283 সারিটি যোগ্যতা অর্জন করবে।
- নোড 3 এ বাছাই করা নোড 4 এ স্ক্যান থেকে সমস্ত সারি গ্রাস করে এবং সেগুলি ক্রম অনুসারে বাছাই করে
Start_Time DESC
। এটি ক্যোয়ারির দ্বারা অনুরোধ করা চূড়ান্ত উপস্থাপনা আদেশ।
- অপ্টিমাইজারটি অনুমান করে যে ৯০ টি সারি (প্রকৃতপক্ষে 93.2791) 100 টি সারি (যোগ দেওয়ার প্রত্যাশিত প্রভাবের জন্য অ্যাকাউন্টিং) ফিরিয়ে আনার পুরো পরিকল্পনার জন্য বাছাই করা থেকে পড়তে হবে।
- নোড 2 এ নেস্টেড লুপগুলি যোগদান করে তার অভ্যন্তরীণ ইনপুট (নিম্ন শাখা )টি 94 বার (আসলে 94.2791) সম্পাদন করবে বলে আশা করা হচ্ছে। প্রযুক্তিগত কারণে নোড 1 এ স্টপ প্যারালালিজম এক্সচেঞ্জের মাধ্যমে অতিরিক্ত সারিটি প্রয়োজন।
- নোড 5 এ স্ক্যান প্রতিটি পুনরাবৃত্তির টেবিলটি পুরোপুরি স্ক্যান করে। এটি সারিগুলি খুঁজে পায় যেখানে
Start_Time
শূন্য নয় এবং State
3 বা 4 হয় এটি প্রতিটি পুনরাবৃত্তিতে 400,875 সারি তৈরি করার অনুমান করা হয়। 94.2791 পুনরাবৃত্তির ওপরে, সারিগুলির মোট সংখ্যা প্রায় 38 মিলিয়ন।
- নোড 2 এ নেস্টেড লুপগুলি যোগদানের পূর্বাভাসকেও প্রয়োগ করে। এটি পরীক্ষা করে যে
Operation_Type
মেলে, Start_Time
নোড 4 Start_Time
থেকে নোড 5 এর চেয়ে কম , Start_Time
নোড 5 Finish_Time
থেকে নোড 4 এর চেয়ে কম হয় এবং দুটি Id
মান মেলে না।
- নোড 1 এ জড়ো স্ট্রিমস (সমান্তরালতা বিনিময় বন্ধ করুন) 100 টি সারি তৈরি হওয়া অবধি প্রতিটি থ্রেড থেকে অর্ডার করা স্ট্রিমগুলি একত্রিত করে। একাধিক স্ট্রিমগুলিতে একত্রিত হওয়ার ক্রম-সংরক্ষণের প্রকৃতি হ'ল পদক্ষেপ 5 এ উল্লিখিত অতিরিক্ত সারিটির প্রয়োজন।
দুর্দান্ত অদক্ষতা স্পষ্টত উপরের 6 এবং 7 ধাপে রয়েছে। প্রতিটি পুনরাবৃত্তির জন্য নোড 5 এ টেবিলটি পুরোপুরি স্ক্যান করা কেবলমাত্র সামান্য যুক্তিসঙ্গত যদি এটি অপটিমাইজারের পূর্বাভাস হিসাবে 94 বার ঘটে happens নোড 2 এ তুলনা করে প্রতি সারিতে ~ 38 মিলিয়ন ডলারের একটি বড় ব্যয়ও।
গুরুতরভাবে, 93/94 সারি সারি লক্ষ্য অনুমানটিও ভুল হওয়ার যথেষ্ট সম্ভাবনা রয়েছে, কারণ এটি মানগুলির বিতরণের উপর নির্ভর করে on অপ্টিমাইজার আরও বিশদ তথ্যের অভাবে ইউনিফর্ম বিতরণ গ্রহণ করে। সাধারণ কথায়, এর অর্থ এই যে যদি সারণীতে থাকা সারিগুলির 1% যোগ্যতা অর্জনের প্রত্যাশা করা হয়, তবে অপ্টিমাইজারটি 1 টি সারণী সন্ধান করার জন্য এটি 100 টি সারি পড়তে হবে reasons
আপনি যদি এই ক্যোয়ারীটি সমাপ্তির দিকে চালিত করেন (যা খুব দীর্ঘ সময় নিতে পারে) তবে আপনি সম্ভবত দেখতে পাবেন যে শেষ পর্যন্ত 100 টি সারি তৈরির জন্য 93/94 টিরও বেশি সারি বাছাই করা থেকে পড়তে হয়েছিল। সবচেয়ে খারাপ ক্ষেত্রে, 100 ম সারিটি বাছাই করা শেষ সারিটি ব্যবহার করে খুঁজে পাওয়া যাবে। নোড 4 এ অপ্টিমাইজারের অনুমানটি সঠিক বলে ধরে নিচ্ছেন, এর অর্থ মোট 15 বিলিয়ন সারিগুলির মতো কোনও কিছুর জন্য নোড 5 38,284 বার স্ক্যান চালানো । স্ক্যানের অনুমানগুলি বন্ধ থাকলে এটি আরও বেশি হতে পারে।
এই কার্যকরকরণ পরিকল্পনায় একটি অনুপস্থিত সূচক সতর্কতাও রয়েছে:
/*
The Query Processor estimates that implementing the following index
could improve the query cost by 72.7096%.
WARNING: This is only an estimate, and the Query Processor is making
this recommendation based solely upon analysis of this specific query.
It has not considered the resulting index size, or its workload-wide
impact, including its impact on INSERT, UPDATE, DELETE performance.
These factors should be taken into account before creating this index.
*/
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Batch_Tasks_Queue] ([Operation_Type],[State],[Start_Time])
INCLUDE ([Id],[Parameters])
অপ্টিমাইজার আপনাকে এই বিষয়ে সতর্ক করে দিচ্ছে যে টেবিলটিতে একটি সূচক যুক্ত করা কর্মক্ষমতা উন্নত করবে।
অতিরিক্ত কলাম ছাড়াই পরিকল্পনা করুন
এটি নোড 6-তে সূচক স্পুল এবং নোড 5 এ ফিল্টার যোগ করে মূলত পূর্বের পরিকল্পনার মতো ঠিক একই পরিকল্পনা The গুরুত্বপূর্ণ পার্থক্যগুলি হ'ল:
- নোড 6 এর সূচক স্পুল একটি ইজিার স্পুল। এটা তোলে সাগ্রহে নীচের স্ক্যান ফল হ্রাস, এবং অস্থির একটি অস্থায়ী সূচক তৈরী করে
Operation_Type
এবং Start_Time
সঙ্গে, Id
একটি অ-কি কলাম হিসাবে।
- নোড 2 এ নেস্টেড লুপস জয়েন এখন সূচীতে যোগ দিন। কোন যোগদানের predicates এখানে মূল্যায়ন করা হয়, এর পরিবর্তে প্রতি পুনরাবৃত্তির বর্তমান মান
Operation_Type
, Start_Time
, Finish_Time
, এবং Id
নোড 4 স্ক্যান থেকে বাইরের উল্লেখ হিসেবে ভেতরের প্রান্তের শাখায় পাঠানো হয়।
- নোড 7 এ স্ক্যানটি একবারে সঞ্চালিত হয়।
- নোড at-এর সূচক স্পুল অস্থায়ী সূচী থেকে সারি সন্ধান করে যেখানে
Operation_Type
বর্তমান বাহ্যিক রেফারেন্স মানটির সাথে মেলে এবং এটি বাহ্যিক এবং রেফারেন্স Start_Time
দ্বারা নির্ধারিত সীমার মধ্যে রয়েছে ।Start_Time
Finish_Time
- নোডে ফিল্টার 5
Id
এর বর্তমান বাহ্যিক রেফারেন্স মানের বিপরীতে বৈষম্যের জন্য সূচক স্পুল থেকে মান পরীক্ষা করে Id
।
মূল উন্নতিগুলি হ'ল:
- অভ্যন্তরীণ পার্শ্ব স্ক্যান শুধুমাত্র একবার সঞ্চালিত হয়
- অন্তর্ভুক্ত কলাম হিসাবে (
Operation_Type
, Start_Time
) এর উপর একটি অস্থায়ী সূচী Id
সূচী নেস্টেড লুপগুলিতে যোগদানের অনুমতি দেয়। সূচিটি প্রতিবার পুরো টেবিলটি স্ক্যান করার পরিবর্তে প্রতিটি পুনরাবৃত্তির সাথে সারি সারি সন্ধান করতে ব্যবহৃত হয়।
আগের মতো, অপ্টিমাইজারটিতে একটি অনুপস্থিত সূচক সম্পর্কে একটি সতর্কতা অন্তর্ভুক্ত রয়েছে:
/*
The Query Processor estimates that implementing the following index
could improve the query cost by 24.1475%.
WARNING: This is only an estimate, and the Query Processor is making
this recommendation based solely upon analysis of this specific query.
It has not considered the resulting index size, or its workload-wide
impact, including its impact on INSERT, UPDATE, DELETE performance.
These factors should be taken into account before creating this index.
*/
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Batch_Tasks_Queue] ([State],[Start_Time])
INCLUDE ([Id],[Operation_Type])
GO
উপসংহার
অতিরিক্ত কলাম ব্যতীত পরিকল্পনাটি দ্রুততর কারণ অপ্টিমাইজারটি আপনার জন্য একটি অস্থায়ী সূচক তৈরি করতে বেছে নিয়েছে।
অতিরিক্ত কলামগুলির সাথে পরিকল্পনাটি অস্থায়ী সূচকটি তৈরি করতে আরও ব্যয়বহুল করে তুলবে। [Parameters
] কলাম হয় nvarchar(2000)
যা সূচক প্রতিটি সারিতে 4000 বাইট পর্যন্ত যোগ হবে। অপ্টিমাইজারকে বোঝাতে অতিরিক্ত ব্যয় যথেষ্ট যে প্রতিটি মৃত্যুদণ্ডের উপর অস্থায়ী সূচী তৈরি করা নিজের জন্য কোনও অর্থ প্রদান করবে না।
অপটিমাইজার উভয় ক্ষেত্রেই সতর্ক করে যে স্থায়ী সূচকটি আরও ভাল সমাধান হবে। সূচকের আদর্শ রচনাটি আপনার বিস্তৃত কাজের চাপের উপর নির্ভর করে। এই নির্দিষ্ট প্রশ্নের জন্য, প্রস্তাবিত সূচকগুলি একটি যুক্তিসঙ্গত প্রারম্ভিক বিন্দু, তবে এতে জড়িত সুবিধা এবং ব্যয়গুলি আপনার বোঝা উচিত।
সুপারিশ
সম্ভাব্য সূচিগুলির বিস্তৃত পরিসীমা এই প্রশ্নের জন্য উপকারী হবে। গুরুত্বপূর্ণ গ্রহণযোগ্যতা হ'ল কিছু ধরণের নন-ক্ল্লাস্টার্ড সূচক প্রয়োজন। প্রদত্ত তথ্য থেকে, আমার মতে একটি যুক্তিসঙ্গত সূচকটি হ'ল:
CREATE NONCLUSTERED INDEX i1
ON dbo.Batch_Tasks_Queue (Start_Time DESC)
INCLUDE (Operation_Type, [State], Finish_Time);
আমি কোয়েরিটি আরও ভালভাবে সংগঠিত করার জন্য প্রলুব্ধ হব [Parameters]
এবং শীর্ষস্থানীয় 100 টি সারি সন্ধান না হওয়া পর্যন্ত ( Id
কী হিসাবে ব্যবহার করে ) ক্লাস্টারড ইনডেক্সে প্রশস্ত কলামগুলি সন্ধান করতে দেরি করব :
SELECT TOP (100)
BTQ1.id,
BTQ2.id,
BTQ3.[Parameters],
BTQ4.[Parameters]
FROM dbo.Batch_Tasks_Queue AS BTQ1
JOIN dbo.Batch_Tasks_Queue AS BTQ2 WITH (FORCESEEK)
ON BTQ2.Operation_Type = BTQ1.Operation_Type
AND BTQ2.Start_Time > BTQ1.Start_Time
AND BTQ2.Start_Time < BTQ1.Finish_Time
AND BTQ2.id != BTQ1.id
-- Look up the [Parameters] values
JOIN dbo.Batch_Tasks_Queue AS BTQ3
ON BTQ3.Id = BTQ1.Id
JOIN dbo.Batch_Tasks_Queue AS BTQ4
ON BTQ4.Id = BTQ2.Id
WHERE
BTQ1.[State] IN (3, 4)
AND BTQ2.[State] IN (3, 4)
AND BTQ1.Operation_Type NOT IN (23, 24, 25, 26, 27, 28, 30)
AND BTQ2.Operation_Type NOT IN (23, 24, 25, 26, 27, 28, 30)
-- These predicates are not strictly needed
AND BTQ1.Start_Time IS NOT NULL
AND BTQ2.Start_Time IS NOT NULL
ORDER BY
BTQ1.Start_Time DESC;
যেখানে [Parameters]
কলামগুলির প্রয়োজন নেই, ক্যোয়ারী এখানে সরল করা যেতে পারে:
SELECT TOP (100)
BTQ1.id,
BTQ2.id
FROM dbo.Batch_Tasks_Queue AS BTQ1
JOIN dbo.Batch_Tasks_Queue AS BTQ2 WITH (FORCESEEK)
ON BTQ2.Operation_Type = BTQ1.Operation_Type
AND BTQ2.Start_Time > BTQ1.Start_Time
AND BTQ2.Start_Time < BTQ1.Finish_Time
AND BTQ2.id != BTQ1.id
WHERE
BTQ1.[State] IN (3, 4)
AND BTQ2.[State] IN (3, 4)
AND BTQ1.Operation_Type NOT IN (23, 24, 25, 26, 27, 28, 30)
AND BTQ2.Operation_Type NOT IN (23, 24, 25, 26, 27, 28, 30)
AND BTQ1.Start_Time IS NOT NULL
AND BTQ2.Start_Time IS NOT NULL
ORDER BY
BTQ1.Start_Time DESC;
FORCESEEK
ইঙ্গিতটি নিশ্চিত অপটিমাইজার বেছে একটি সূচীবদ্ধ নেস্টেড loops পরিকল্পনা সাহায্য নেই (সেখানে একটি হ্যাশ অথবা (অনেকগুলি অনেক) একত্রীকরণ অন্যথায় যোগদান নির্বাচন করতে অপটিমাইজার জন্য একটি খরচ ভিত্তিক প্রলোভন, যা ভাল এই ধরনের সঙ্গে কাজ করার না থাকে হয় অনুশীলনে জিজ্ঞাসা করুন Both
বিকল্প
যদি ক্যোয়ারী (এর নির্দিষ্ট মানগুলি সহ) পড়ার পারফরম্যান্সের জন্য বিশেষভাবে সমালোচিত হত, আমি পরিবর্তে দুটি ফিল্টার সূচক বিবেচনা করব:
CREATE NONCLUSTERED INDEX i1
ON dbo.Batch_Tasks_Queue (Start_Time DESC)
INCLUDE (Operation_Type, [State], Finish_Time)
WHERE
Start_Time IS NOT NULL
AND [State] IN (3, 4)
AND Operation_Type <> 23
AND Operation_Type <> 24
AND Operation_Type <> 25
AND Operation_Type <> 26
AND Operation_Type <> 27
AND Operation_Type <> 28
AND Operation_Type <> 30;
CREATE NONCLUSTERED INDEX i2
ON dbo.Batch_Tasks_Queue (Operation_Type, [State], Start_Time)
WHERE
Start_Time IS NOT NULL
AND [State] IN (3, 4)
AND Operation_Type <> 23
AND Operation_Type <> 24
AND Operation_Type <> 25
AND Operation_Type <> 26
AND Operation_Type <> 27
AND Operation_Type <> 28
AND Operation_Type <> 30;
[Parameters]
কলামটির প্রয়োজন নেই এমন ক্যোয়ারির জন্য , ফিল্টারড সূচকগুলি ব্যবহার করে আনুমানিক পরিকল্পনাটি হ'ল:
সূচক স্ক্যানটি কোনও অতিরিক্ত পূর্বাভাসের মূল্যায়ন না করে স্বয়ংক্রিয়ভাবে সমস্ত যোগ্যতার সারি ফেরত দেয়। সূচক নেস্টযুক্ত লুপগুলিতে যোগদানের প্রতিটি পুনরাবৃত্তির জন্য, সূচক সন্ধান দুটি অনুসন্ধানের ক্রিয়া সম্পাদন করে:
- অসমতার উপর রেজিডুয়াল প্রিডিকেট এবং তার পরে মানগুলির পরিসীমা অনুসন্ধান করে
Operation_Type
এবং State
= 3 এ প্রিফিক্স ম্যাচ সন্ধান করুন ।Start_Time
Id
- অসমতার উপর রেসিডুয়াল প্রিডিকেট এবং তার পরে মান 4 এর সন্ধান করে উপসর্গের মিল
Operation_Type
এবং State
= 4 এ অনুসন্ধান করুন ।Start_Time
Id
যেখানে [Parameters]
কলামটি প্রয়োজন সেখানে ক্যোয়ারী প্ল্যান প্রতিটি টেবিলের জন্য সর্বাধিক 100 সিঙ্গলটন লুকআপ যুক্ত করে:
একটি চূড়ান্ত নোট হিসাবে, আপনি numeric
প্রযোজ্য পরিবর্তে বিল্ট-ইন স্ট্যান্ডার্ড পূর্ণসংখ্যার প্রকারগুলি বিবেচনা করা উচিত ।