আমার যত্ন নেওয়া একটি কলাম নির্বাচন করার চেয়ে কেন এই ক্যোয়ারির ফলাফলের সমস্ত কলামগুলি দ্রুত নির্বাচন করা হচ্ছে?


13

আমার একটি ক্যোয়ারী রয়েছে যেখানে ব্যবহারের ফলে select *কেবলমাত্র কম পড়া হয় না, তবে ব্যবহারের চেয়ে সিপিইউর সময় উল্লেখযোগ্যভাবে কম ব্যবহৃত হয় select c.Foo

এটি ক্যোয়ারী:

select top 1000 c.ID
from ATable a
    join BTable b on b.OrderKey = a.OrderKey and b.ClientId = a.ClientId
    join CTable c on c.OrderId = b.OrderId and c.ShipKey = a.ShipKey
where (a.NextAnalysisDate is null or a.NextAnalysisDate < @dateCutOff)
    and b.IsVoided = 0
    and c.ComplianceStatus in (3, 5)
    and c.ShipmentStatus in (1, 5, 6)
order by a.LastAnalyzedDate

এটি 2,473,658 যৌক্তিক পাঠ সহ শেষ হয়েছে, বেশিরভাগ সারণী বিতে এটি 26,562 সিপিইউ ব্যবহার করে এবং এর মেয়াদকাল 7,965 ছিল।

এটি উত্পন্ন ক্যোয়ারী পরিকল্পনা:

একটি একক কলামের মান নির্বাচন করা থেকে পরিকল্পনা করুন PasteThePlan এ: https://www.brentozar.com/pastetheplan/?id=BJAp2mQIQ

আমি যখন পরিবর্তন c.IDকরি *, তখন কোয়েরিটি 107,049 লজিকাল রিডের সাথে শেষ হয়েছিল, তিনটি সারণির মধ্যে প্রায় সমানভাবে ছড়িয়ে পড়ে। এটি 4,266 সিপিইউ ব্যবহার করেছে এবং এর মেয়াদ ছিল 1,147।

এটি উত্পন্ন ক্যোয়ারী পরিকল্পনা:

সমস্ত মান নির্বাচন করা থেকে পরিকল্পনা করুন PasteThePlan এ: https://www.brentozar.com/pastetheplan/?id=SyZYn7QUQ

আমি জো ওবিশের পরামর্শযুক্ত ক্যোয়ারী ইঙ্গিতগুলি ব্যবহার করার চেষ্টা করেছি, এই ফলাফলগুলি সহ:
select c.IDইঙ্গিত ছাড়াই: https://www.brentozar.com/pastetheplan/?id=SJfBdOELm
select c.ID ইঙ্গিত সহ: https://www.brentozar.com/pastetheplan/ ? id = B1W ___ N87
select * ইঙ্গিত ছাড়াই: https://www.brentozar.com/pastetheplan/?id=HJ6qddEIm
select * ইঙ্গিত সহ: https://www.brentozar.com/pastetheplan/?id=rJhhudNIQ

ব্যবহার OPTION(LOOP JOIN)সঙ্গে ইঙ্গিতটি select c.IDআয়তন বহুলাংশে এর ইঙ্গিতটি ছাড়া সংস্করণের সাথে তুলনা পড়া কমিয়ে হয়নি, কিন্তু এটি এখনও 4x সম্পর্কে সংখ্যা করছে সার্চ এর select *কোনো ইঙ্গিত ছাড়া জিজ্ঞাস্য। যোগ করার পদ্ধতি OPTION(RECOMPILE, HASH JOIN)থেকে select *ক্যোয়ারী এটা অনেক খারাপ অন্য কিছু আর আমি চেষ্টা করেছি সঞ্চালন করেন।

টেবিলগুলি এবং তাদের সূচকগুলি ব্যবহার করে পরিসংখ্যান আপডেট করার পরে WITH FULLSCAN, select c.IDক্যোয়ারীটি আরও দ্রুত চলছে:
select c.IDআপডেটের আগে: https://www.brentozar.com/pastetheplan/?id=SkiYoOEUm
select * আপডেটের আগে: https://www.brentozar.com/ পেস্টেথপ্লান /? আইডি = রাইরভোডইউএক্স
select c.ID আপডেটের পরে: https://www.brentozar.com/pastetheplan/?id=B1MRoO487
select * আপডেটের পরে: https://www.brentozar.com/pastetheplan/?id=Hk7si_V8m

select *এখনও select c.IDমোট সময়কাল এবং মোট পাঠের দিক থেকে আরও কার্যকর ( select *প্রায় অর্ধেক পঠন রয়েছে) তবে এটি আরও সিপিইউ ব্যবহার করে না। সামগ্রিকভাবে তারা আপডেটের তুলনায় অনেক বেশি কাছাকাছি, তবে পরিকল্পনাগুলি এখনও পৃথক।

২০১৪ সালের সামঞ্জস্যতা মোডে এবং ২০১৪ সালে একই আচরণ দেখা যায়। দুটি পরিকল্পনার মধ্যে বৈষম্যকে কী ব্যাখ্যা করতে পারে? এটি কি হতে পারে যে "সঠিক" সূচকগুলি তৈরি করা হয়নি? পরিসংখ্যান কিছুটা পুরানো হয়ে যাওয়ার কারণ হতে পারে?

আমি পূর্বাভাসটিকে ONএকাধিক উপায়ে যোগদানের অংশ পর্যন্ত স্থানান্তরিত করার চেষ্টা করেছি , তবে ক্যোয়ারি প্ল্যান প্রতিবারের মত একই।

সূচকের পুনর্নির্মাণের পরে

আমি ক্যোয়ারীতে জড়িত তিনটি টেবিলে সমস্ত সূচী পুনরায় তৈরি করেছি। c.IDএখনও সর্বাধিক পঠন করছে (দ্বিগুণেরও বেশি *), তবে সিপিইউ ব্যবহারটি *সংস্করণের প্রায় অর্ধেক । c.IDসংস্করণ এছাড়াও শ্রেণীবিভাজন উপর tempdb মধ্যে চিত্তভ্রংশ ATable:
c.ID: https://www.brentozar.com/pastetheplan/?id=HyHIeDO87
* : https://www.brentozar.com/pastetheplan/?id=rJ4deDOIQ

আমি এটিকে সমান্তরালতা ছাড়াই পরিচালিত করার জন্য জোর করেও চেষ্টা করেছি এবং এটি আমাকে সেরা পারফরম্যান্স ক্যোয়ারী দিয়েছে: https://www.brentozar.com/pastetheplan/?id=SJn9-vuLX

আমি বড় সূচকগুলির অনুসন্ধানের পরে অপারেটরদের মৃত্যুদন্ড গণনা করেছি যা কেবলমাত্র একক থ্রেডেড সংস্করণে এক হাজার বার কার্যকর করা অর্ডার করছে, তবে সমান্তরাল সংস্করণে বিভিন্ন অপারেটরের ২,6২২ থেকে ৪,৩১৫ টি ফাঁসির মধ্যে উল্লেখযোগ্যভাবে আরও কিছু করেছে।

উত্তর:


4

এটি সত্য যে আরও কলামগুলি নির্বাচন করে বোঝায় যে এসকিউএল সার্ভারকে ক্যোয়ারির অনুরোধকৃত ফলাফলগুলি পেতে আরও কঠোর পরিশ্রম করতে হবে। যদি ক্যোয়ারী অপ্টিমাইজার উভয় প্রশ্নের জন্য নিখুঁত ক্যোয়ারী প্ল্যান নিয়ে আসতে সক্ষম হয় তবে এটি আশা করা যুক্তিসঙ্গত হবেSELECT *সমস্ত টেবিল থেকে সমস্ত কলাম নির্বাচন করে এমন ক্যোয়ারীর চেয়ে দীর্ঘতর চলার জন্য ক্যোয়ারী। আপনার জুটির প্রশ্নের জন্য আপনি বিপরীতটি পর্যবেক্ষণ করেছেন। ব্যয়ের তুলনা করার সময় আপনাকে সতর্কতা অবলম্বন করা উচিত, তবে ধীর প্রশ্নের সাথে মোট আনুমানিক ব্যয় হয়েছে 1090.08 অপ্টিমাইজার ইউনিট এবং দ্রুত ক্যোয়ারিতে মোট আনুমানিক ব্যয় হয় 6823.11 অপটিমাইজার ইউনিট। এই ক্ষেত্রে, এটি বলা যেতে পারে যে সর্বোত্তম ক্যোয়ারী ব্যয়ের ব্যয় নির্ধারণের সাথে অপটিমাইজার একটি খারাপ কাজ করে। এটি আপনার নির্বাচন * প্রশ্নের জন্য একটি আলাদা পরিকল্পনা বেছে নিয়েছে এবং এটি পরিকল্পনাটি আরও ব্যয়বহুল হওয়ার প্রত্যাশা করেছিল, তবে এখানে এটি ছিল না। এই ধরণের অমিলটি বিভিন্ন কারণে ঘটতে পারে এবং সর্বাধিক সাধারণ কারণগুলির মধ্যে একটি হ'ল কার্ডিনালিটি অনুমানের সমস্যা। অপারেটর ব্যয়গুলি মূলত কার্ডিনালিটির অনুমানের দ্বারা নির্ধারিত হয়। যদি কোনও পরিকল্পনার মূল পয়েন্টে কার্ডিনালটির অনুমানটি সঠিক না হয় তবে পরিকল্পনার মোট ব্যয় বাস্তবতার প্রতিফলন ঘটতে পারে না। এটি একটি স্থূল ওভারসিম্প্লিফিকেশন তবে আমি আশা করি যে এখানে কী চলছে তা বোঝার জন্য এটি সহায়ক হবে।

আসুন SELECT *একটি কলামটি নির্বাচন করার চেয়ে কেন কোয়েরি বেশি ব্যয়বহুল হতে পারে তা নিয়ে আলোচনা শুরু করুন । SELECT *ক্যোয়ারী noncovering ইনডেক্স, যেটার অর্থ হতে পারে অপটিমাইজার উপরন্তু কাজ করতে কলাম দরকার সব পেতে প্রয়োজন বা এটি একটি বড় সূচক থেকে পড়া করার প্রয়োজন হতে পারে মধ্যে কিছু আচ্ছাদন ইনডেক্স চালু হতে পারে।SELECT *বৃহত্তর মধ্যবর্তী ফলাফল সেটগুলির ফলাফলও হতে পারে যা ক্যোয়ারী কার্যকর করার সময় প্রক্রিয়া করা প্রয়োজন। আপনি উভয় ক্যোয়ারেই আনুমানিক সারির আকারগুলি দেখে এটি ক্রিয়াতে দেখতে পাচ্ছেন। দ্রুত ক্যোয়ারিতে আপনার সারির আকারগুলি 664 বাইট থেকে 3019 বাইট পর্যন্ত হয়। ধীর ক্যোয়ারিতে আপনার সারির আকারগুলি 19 থেকে 36 বাইট পর্যন্ত। ধরণের বা হ্যাশ বিল্ডগুলির মতো ব্লকিং অপারেটরগুলির বৃহত্তর সারি আকারের ডেটার জন্য বেশি দাম পড়বে কারণ এসকিউএল সার্ভার জানে যে বৃহত পরিমাণে ডেটা বাছাই করা বা এটি একটি হ্যাশ টেবিলের দিকে পরিণত করা আরও ব্যয়বহুল।

দ্রুত ক্যোয়ারীর দিকে নজর দিলে, অপ্টিমাইজারটি অনুমান করে যে এটির জন্য 2.4 মিলিয়ন সূচীটি করা দরকার Database1.Schema1.Object5.Index3। সেখান থেকে বেশিরভাগ পরিকল্পনা ব্যয়ই আসে। তবুও আসল পরিকল্পনাটি প্রকাশ করে যে কেবল ১৩৩৩ সূচক সন্ধানটি ওই অপারেটরে করা হয়েছিল। যদি আপনি সেই লুপের বাইরের অংশগুলিতে যোগ দেওয়ার জন্য অনুমিত সারিগুলির সাথে প্রকৃত তুলনা করেন তবে আপনি বড় পার্থক্য দেখতে পাবেন। অপ্টিমাইজারটি মনে করে যে ক্যোয়ারির ফলাফলের জন্য প্রয়োজনীয় প্রথম 1000 সারিটি খুঁজতে আরও অনেক সূচকের সন্ধান প্রয়োজন হবে। এজন্য ক্যোয়ারিতে তুলনামূলকভাবে উচ্চ ব্যয়ের পরিকল্পনা রয়েছে তবে এত তাড়াতাড়ি শেষ হয়েছে: যে অপারেটরটি সবচেয়ে ব্যয়বহুল বলে পূর্বাভাস দেওয়া হয়েছিল তার প্রত্যাশিত কাজের 0.1% এর চেয়ে কম কাজ করেছে।

ধীরে ধীরে ক্যোয়ারীটি দেখে আপনি বেশিরভাগ হ্যাশ যোগদানের সাথে একটি পরিকল্পনা পেয়েছেন (আমি বিশ্বাস করি লুপ জয়েন কেবল স্থানীয় ভেরিয়েবলের সাথে ডিল করার জন্য রয়েছে)। কার্ডিনালিটির অনুমানগুলি অবশ্যই নিখুঁত নয়, তবে একমাত্র আসল অনুমানের সমস্যাটি সাজানোর সাথে শেষে রয়েছে। আমার সন্দেহ হয় বেশিরভাগ সময় কয়েক মিলিয়ন সারি দিয়ে টেবিলগুলির স্ক্যানে ব্যয় হয়।

অন্যান্য সংস্করণের সাথে সম্পর্কিত ক্যোয়ারী পরিকল্পনাকে জোর করতে কোয়েরির উভয় সংস্করণে কোয়েরি ইঙ্গিতগুলি যুক্ত করা আপনাকে সহায়ক বলে মনে করতে পারে। অপ্টিমাইজার কেন তার পছন্দসই কিছু তৈরি করেছে তা নির্ধারণের জন্য ক্যোরির ইঙ্গিতগুলি ভাল সরঞ্জাম হতে পারে। আপনি যদি ক্যোয়ারিতে যুক্ত OPTION (RECOMPILE, HASH JOIN)করেন তবে SELECT *আমি আশা করি আপনি হ্যাশ যোগদানের ক্যোয়ারিতে অনুরূপ কোয়েরি পরিকল্পনাটি দেখতে পাবেন। আমি আরও আশা করি যে হ্যাশ যোগদানের পরিকল্পনার জন্য ক্যোয়ারী ব্যয়গুলি অনেক বেশি হবে কারণ আপনার সারির আকারগুলি আরও বড়। সুতরাং হ্যাশ যোগদানের ক্যোয়ারী SELECT *কোয়েরির জন্য বেছে নেওয়া হয়নি বলেই হতে পারে । যদি আপনি OPTION (LOOP JOIN)কেবলমাত্র একটি কলাম নির্বাচন করে এমন ক্যোয়ারিতে যুক্ত করেন তবে আমি প্রত্যাশা করি যে এর জন্য একটির মতো একটি কোয়েরি প্ল্যান দেখবেনSELECT *প্রশ্ন. এই ক্ষেত্রে, সারির আকার হ্রাস করার সামগ্রিক ক্যোয়ারী ব্যয়ের উপর খুব বেশি প্রভাব ফেলতে হবে না। আপনি মূল লুকগুলি এড়িয়ে যেতে পারেন তবে এটি আনুমানিক ব্যয়ের একটি ছোট শতাংশ।

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


আপনার বিস্তৃত এবং তথ্যমূলক উত্তরের জন্য আপনাকে অনেক ধন্যবাদ। আপনার প্রস্তাবিত ইঙ্গিতগুলি যুক্ত করার চেষ্টা করেছি। এটি select c.IDক্যোয়ারীটিকে আরও দ্রুত তৈরি করেছে তবে এটি এখনও কিছু অতিরিক্ত কাজ করছে যা select *কোয়েরিটি, ইঙ্গিত ছাড়াই করে।
এল। মিলার

2

পুরানো পরিসংখ্যান অবশ্যই অপ্টিমাইজারটিকে ডেটা সন্ধানের একটি দুর্বল পদ্ধতি চয়ন করতে পারে। আপনি কি সূচকে কিছু করতে UPDATE STATISTICS ... WITH FULLSCANবা পূর্ণ করার REBUILDচেষ্টা করেছেন? এটি ব্যবহার করে দেখুন এবং এটি সাহায্য করে কিনা।

হালনাগাদ

ওপির একটি আপডেট অনুসারে:

টেবিলগুলি এবং তাদের সূচকগুলি ব্যবহার করে পরিসংখ্যান আপডেট করার পরে WITH FULLSCAN, select c.IDক্যোয়ারীটি আরও দ্রুত চলছে

সুতরাং, এখন, যদি কেবল পদক্ষেপ নেওয়া হয় UPDATE STATISTICS, তবে একটি সূচক করার চেষ্টা করুন REBUILD(না REORGANIZE) যেমনটি আমি দেখেছি যে অনুমিত সারি গণনা যেখানে সহায়তা উভয় UPDATE STATISTICSএবং সূচক উভয়ই REORGANIZEনয়।


আমি উইকএন্ডে পুনর্নির্মাণের জন্য জড়িত তিনটি টেবিলের সমস্ত সূচক পেতে সক্ষম হয়েছি এবং ফলাফলগুলি প্রতিফলিত করতে আমার পোস্ট আপডেট করেছি।
এল। মিলার

-1
  1. আপনি কি দয়া করে সূচক স্ক্রিপ্টগুলি অন্তর্ভুক্ত করতে পারেন?
  2. আপনি কি "প্যারামিটার স্নিফিং" দিয়ে সম্ভাব্য সমস্যাগুলি সরিয়ে দিয়েছেন? https://www.mssqltips.com/sqlservertip/3257/different-approaches-to-correct-sql-server-parameter-sniffing/
  3. আমি এই কৌশলটি কিছু ক্ষেত্রে সহায়ক হতে পেরেছি:
    ক) প্রতিটি বিস্তৃত টেবিলটি সাবকিউরি হিসাবে পুনরায় লিখুন, এই বিধিগুলি অনুসরণ করে:
    খ) নির্বাচন করুন - প্রথম কলামগুলিতে যোগদান করুন
    গ) পূর্বনির্ধারিতগুলি - স্ব স্ব সাবকিউরিয়ায় স্থানান্তরিত করুন
    d) অর্ডার - তাদের মধ্যে যান সংশ্লিষ্ট সাব-
    কোয়্যারিগুলি, যোগ করুন কলম্বস প্রথম অনুসারে বাছাই করুন your) আপনার চূড়ান্ত বাছাইয়ের জন্য একটি মোড়কের ক্যোয়ারী যুক্ত করুন এবং নির্বাচন করুন।

ধারণাটি হ'ল প্রতিটি উপ-স্তরের অভ্যন্তরে যোগদানের কলামগুলিকে প্রাক-বাছাই করা, প্রতিটি নির্বাচিত তালিকায় প্রথমে জোড় কলামগুলি স্থাপন করা।

এখানে আমি যা বোঝাতে চাইছি ...

SELECT ... wrapper query
FROM
(
    SELECT ...
    FROM
        (SELECT ClientID, ShipKey, NextAnalysisDate
         FROM ATABLE
         WHERE (a.NextAnalysisDate is null or a.NextAnalysisDate < @dateCutOff) -- Predicates
         ORDER BY OrderKey, ClientID, LastAnalyzedDate  ---- Pre-sort the join columns
        ) as a
        JOIN 
        (SELECT OrderKey, ClientID, OrderID, IsVoided
         FROM BTABLE
         WHERE IsVoided = 0             ---- Include all predicates
         ORDER BY OrderKey, OrderID, IsVoided       ---- Pre-sort the join columns
        ) as b ON b.OrderKey = a.OrderKey and b.ClientId = a.ClientId
        JOIN
        (SELECT OrderID, ShipKey, ComplianceStatus, ShipmentStatus, ID
         FROM CTABLE
         WHERE ComplianceStatus in (3, 5)       ---- Include all predicates
             AND ShipmentStatus in (1, 5, 6)        ---- Include all predicates
         ORDER BY OrderID, ShipKey          ---- Pre-sort the join columns
        ) as c ON c.OrderId = b.OrderId and c.ShipKey = a.ShipKey
) as d
ORDER BY d.LastAnalyzedDate

1
১. আমি মূল পোস্টে সূচক ডিডিএল স্ক্রিপ্টগুলি যুক্ত করার চেষ্টা করব, এটি "স্ক্রাব" করতে কিছুটা সময় নিতে পারে। ২. দৌড়ানোর আগে প্ল্যান ক্যাশে দুটি সাফ করে দিয়ে এবং বাইন্ড প্যারামিটারকে একটি আসল মান দিয়ে প্রতিস্থাপন করে আমি এই সম্ভাবনাটি পরীক্ষা করেছিলাম। 3. আমি এই চেষ্টা করেছেন, কিন্তু ORDER BYএকটি শীর্ষ, FORXML, ইত্যাদি আমি ছাড়া এটা চেষ্টা ছাড়া একটি subquery অবৈধ ORDER BYক্লজ কিন্তু এটি একই পরিকল্পনা ছিল।
এল। মিলার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.