কেন শীর্ষ 1 যুক্ত করা নাটকীয়ভাবে অভিনয় খারাপ করে?


39

আমার মোটামুটি সহজ প্রশ্ন আছে

SELECT TOP 1 dc.DOCUMENT_ID,
        dc.COPIES,
        dc.REQUESTOR,
        dc.D_ID,
        cj.FILE_NUMBER
FROM DOCUMENT_QUEUE dc
JOIN CORRESPONDENCE_JOURNAL cj
    ON dc.DOCUMENT_ID = cj.DOCUMENT_ID
WHERE dc.QUEUE_DATE <= GETDATE()
  AND dc.PRINT_LOCATION = 2
ORDER BY cj.FILE_NUMBER

এটি আমাকে ভয়াবহ পারফরম্যান্স দিচ্ছে (যেমন এটি শেষ হওয়ার জন্য অপেক্ষা করার মতো মাথা ঘামায় না)। ক্যোয়ারী প্ল্যানটি এমন দেখাচ্ছে:

এখানে চিত্র বর্ণনা লিখুন

তবে আমি যদি অপসারণ করি তবে TOP 1আমি এমন একটি পরিকল্পনা পাই যা দেখতে এই জাতীয় দেখায় এবং এটি 1-2 সেকেন্ডে চলে:

এখানে চিত্র বর্ণনা লিখুন

সঠিক পিকে & ইনডেক্সিং নীচে।

সত্য যে TOP 1ক্যোয়ারী পরিকল্পনা আমাকে অবাক করে না পরিবর্তিত, আমি শুধু একটু বিস্মিত যে এটা এত খারাপ আছি।

দ্রষ্টব্য: আমি এই পোস্টের ফলাফলগুলি পড়েছি এবং একটি Row Goalইত্যাদির ধারণাটি বুঝতে পেরেছি । বর্তমানে আমি তথ্যকে একটি টেম্প টেবিলের মধ্যে ফেলে দিচ্ছি তারপরে প্রথম সারিটি টানতে। আমি আরও ভাল পদ্ধতি আছে কিনা আমি ভাবছি।

সম্পাদনা আসলে এখানে পরে এই পড়া মানুষের জন্য তথ্য কিছু অতিরিক্ত টুকরা আছে।

  • ডকুমেন্ট_কিউ - পিকে / সিআই হল ডি_আইডি এবং এতে it 5k সারি রয়েছে।
  • চিঠিপত্র_জার্নাল - পিকে / সিআই হ'ল FILE_NUMBER, CORRESPONDENCE_ID এবং এতে ~ 1.4 মিলিয়ন সারি রয়েছে।

যখন আমি শুরু করেছি তখন অন্য কোনও সূচক ছিল না। আমি চিঠিপত্রের_ জার্নালে (ডকুমেন্ট_আইডি, ফাইল_নবার) এর সাথে একটি দিয়ে শেষ করেছি


1
আপনার কাছে কি কোনও বিদেশী কী বাধা DOCUMENT_IDরয়েছে যা দুটি টেবিলের মধ্যে সম্পর্ককে কার্যকর করে (বা প্রতিটি রেকর্ডের সাথে CORRESPONDENCE_JOURNALকোনও মিলের রেকর্ড রয়েছে DOCUMENT_QUEUE)?
ড্যানিয়েল হুটমাচার

উত্তর:


28

জোর করে একটি হ্যাশ যোগ দেওয়ার চেষ্টা করুন *

SELECT TOP 1 
       dc.DOCUMENT_ID,
       dc.COPIES,
       dc.REQUESTOR,
       dc.D_ID,
       cj.FILE_NUMBER
FROM DOCUMENT_QUEUE dc
INNER HASH JOIN CORRESPONDENCE_JOURNAL cj
        ON dc.DOCUMENT_ID = cj.DOCUMENT_ID
       AND dc.QUEUE_DATE <= GETDATE()
       AND dc.PRINT_LOCATION = 2
ORDER BY cj.FILE_NUMBER

অপ্টিমাইজার সম্ভবত ভেবেছিল একটি লুপ শীর্ষ 1 এর সাথে আরও ভাল হতে চলেছে এবং সেই ধরণের অর্থটি তৈরি হয় তবে বাস্তবে এটি এখানে কাজ করে না। এখানে কেবল একটি অনুমান তবে সম্ভবত সেই স্পুলের আনুমানিক ব্যয়টি বন্ধ ছিল - এটি TEMPDB ব্যবহার করে - আপনার পক্ষে খারাপভাবে পারফর্ম করা TEMPDB থাকতে পারে।


* যোগদানের ইঙ্গিতগুলি সম্পর্কে সতর্কতা অবলম্বন করুন , কারণ তারা প্রশ্নের সারণীতে টেবিলগুলির লিখিত ক্রমটি মেলানোর জন্য পরিকল্পনার টেবিল অ্যাক্সেস অর্ডারকে জোর করে (ঠিক যেমন OPTION (FORCE ORDER)নির্দিষ্ট করা হয়েছে)। ডকুমেন্টেশন লিঙ্ক থেকে:

বিএল এক্সট্র্যাক্ট

এটি উদাহরণে কোনও অযাচিত প্রভাব ফেলতে পারে না, তবে সাধারণভাবে এটি খুব ভাল। FORCE ORDER(নিহিত বা সুস্পষ্ট) একটি খুব শক্তিশালী ইঙ্গিত যা কার্যকর করার আদেশের বাইরে চলে যায়; এটি আংশিক সমষ্টি এবং পুনর্বিন্যাস সহ অনেকগুলি অপ্টিমাইজার কৌশল প্রয়োগ করা বাধা দেয়।

উপযুক্ত প্রশ্নের ক্ষেত্রে একটি OPTION (HASH JOIN) ক্যোয়ারী ইঙ্গিতটি কম অনুপ্রবেশকারী হতে পারে, যেহেতু এটি বোঝায় না FORCE ORDER। এটি কোয়েরিতে সমস্ত যোগদানের ক্ষেত্রে প্রযোজ্য। অন্যান্য সমাধান উপলব্ধ।


1
সঠিক উত্তরটির মতো মনে হচ্ছে এবং এটির এবং সহজ পরিকল্পনার মধ্যে একমাত্র তফাতটি ছিল সামনের দিকে অতিরিক্ত বাছাই করা।
কেনেথ ফিশার

3
নিশ্চিত না যে আমি এই উত্তরটি পছন্দ করি। যোগদানের ইঙ্গিতগুলি খুব আক্রমণাত্মক। কিছু সাধারণ সূচী পরিবর্তনগুলি প্রথমে চেষ্টা করা উচিত, উদাহরণস্বরূপ তারিখ কলামে সূচি।
usr

@ ইউএসআর এটি একটি সাধারণ পিকে যোগদান যা এক সেকেন্ডেরও কম সময়ে চলে। এখানে বেশ নিরাপদ বাজি।
পেপারাজো

4
একটি হ্যাশ যোগ দিতে বাধ্য করার জন্য, আপনি বড় টেবিলের স্ক্যান করতে বাধ্য করছেন। আরও ভাল বিকল্প আছে।
রব ফারলি

30

আপনি যেহেতু সঠিক পরিকল্পনাটি পেয়েছেন, তাই ORDER BYআপনি কেবল নিজের TOPঅপারেটরটি রোল করতে পারেন ?

SELECT DOCUMENT_ID, COPIES, REQUESTOR, D_ID, FILE_NUMBER
FROM (
    SELECT dc.DOCUMENT_ID,
           dc.COPIES,
           dc.REQUESTOR,
           dc.D_ID,
           cj.FILE_NUMBER,
           ROW_NUMBER() OVER (ORDER BY cj.FILE_NUMBER) AS _rownum
    FROM DOCUMENT_QUEUE dc
    INNER JOIN CORRESPONDENCE_JOURNAL cj
        ON dc.DOCUMENT_ID = cj.DOCUMENT_ID
    WHERE dc.QUEUE_DATE <= GETDATE()
      AND dc.PRINT_LOCATION = 2
) AS sub
WHERE _rownum=1;

আমার মনে, ROW_NUMBER()উপরের জন্য ক্যোয়ারী প্ল্যানটি একই রকম হওয়া উচিত যেমন আপনার কোনও ছিল ORDER BY। ক্যোয়ারী প্ল্যানের এখন একটি সেগমেন্ট, সিকোয়েন্স প্রজেক্ট এবং শেষ পর্যন্ত একটি ফিল্টার অপারেটর থাকা উচিত, বাকিটি আপনার ভাল পরিকল্পনার মতো দেখতে হবে।


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

10
@ কেনেথফিশার, ফ্রিসবির উত্তর সহজ, তবে কোনও স্লেজহ্যামার স্ট্যান্ডার্ড পেরেক চালিত করে স্ট্যান্ডার্ড হাতুড়ির চেয়ে সহজভাবে। এটি প্রচুর ঝুঁকি নিয়ে আসে, বিশেষত যদি দীর্ঘ অতিক্রমের জন্য রেখে যায়। আমি টেস্টিং বা সম্ভবত বাদে এর মতো ইঙ্গিতগুলি ব্যবহার করব না, একটি ফ্রঞ্জ ব্যতিক্রম হতে পারে।
স্টিভ মঙ্গিয়ামালী

@ স্টেভে মঙ্গমাইজালি এই বিশেষ ক্ষেত্রে কেবলমাত্র একজনই যোগ দিচ্ছেন যাতে অনেকগুলি উদ্বেগ দূরে যায়। আমি একটি যোগদানের ইঙ্গিত ব্যবহার করার ঝুঁকি সম্পর্কে সচেতন (বা ক্যোয়ার ইঙ্গিত) আমি কেবলমাত্র মনে করি এটি এ ক্ষেত্রে ন্যায়সঙ্গত।
কেনেথ ফিশার

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

29

সম্পাদনা: +1 এই পরিস্থিতিতে কাজ করে কারণ এটি প্রমাণ করে যে FILE_NUMBERএটি একটি পূর্ণসংখ্যার শূন্য প্যাডযুক্ত স্ট্রিং সংস্করণ। স্ট্রিংগুলির জন্য এখানে আরও ভাল সমাধান যুক্ত করা ''(খালি স্ট্রিং) সংযোজন করা হয়, কারণ একটি মান সংযোজন ক্রমকে প্রভাবিত করতে পারে বা সংখ্যার জন্য এমন কিছু যুক্ত করতে পারে যা একটি ধ্রুবক তবে একটি অ-নিরোধক ফাংশন ধারণ করে sign(rand()+1)। 'বাছাই ভাঙ্গা' ধারণাটি এখানে এখনও বৈধ, এটি কেবল আমার পদ্ধতিটি আদর্শ ছিল না।

+1 টি

না, আমি বোঝাতে চাই না যে আমি কোনও কিছুর সাথে একমত হচ্ছি, এর অর্থ একটি সমাধান হিসাবে। আপনি যদি আপনার ক্যোয়ারিতে পরিবর্তন করেন ORDER BY cj.FILE_NUMBER + 1তবে the TOP 1ক্যটি অন্যরকম আচরণ করবে।

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

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

সুতরাং আপনি যদি ORDER BYপুরোপুরি বাদ পড়ে থাকেন , আমি আশা করি আপনি এমন একটি পরিকল্পনা পেয়ে যাবেন যা একটি নেস্টেড লুপের সাথে জড়িত ছিল, ডি কিউয়ের সারিগুলিতে পুনরাবৃত্তি করে, সিলের উপস্থিতি নিশ্চিত করার জন্য সিজে সন্ধান করে। এবং সহ TOP 1, এটি একটি একক সারি টানা যাওয়ার পরে থামবে।

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

হ্যাশ ম্যাচটি অগত্যা জঘন্য নয়, তবে আপনি যদি ডি কিউ থেকে ফিরে আসা সারিগুলির সেটটি সিজে থেকে অনেক ছোট হন (যেমনটি আমি এটি প্রত্যাশা করতাম), তবে হ্যাশ ম্যাচটি সিজে-তে আরও অনেক কিছু স্ক্যান করে চলেছে is এটি প্রয়োজন তুলনায়।

দ্রষ্টব্য: আমি +0 এর পরিবর্তে +1 ব্যবহার করেছি কারণ ক্যোয়ারী অপ্টিমাইজারটি সম্ভবত এটি চিনতে পারে যে +0 কিছুই পরিবর্তন করে না। অবশ্যই, একই জিনিসটি এখন +1 এ প্রয়োগ করা যেতে পারে, যদি এখন না হয় তবে ভবিষ্যতের কোনও সময়ে।


7

আমি এই পোস্টের ফলাফলগুলি পড়েছি এবং একটি সারি গোলের ধারণা ইত্যাদি বুঝতে পেরেছি What আমি কী উত্সাহী তা হল কীভাবে আমি ক্যোয়ারি পরিবর্তন করতে পারি যাতে এটি আরও ভাল পরিকল্পনা ব্যবহার করে

যোগ করা OPTION (QUERYTRACEON 4138)চূড়ান্ত পরিকল্পনা সম্পর্কে অত্যধিক প্রেসক্রিপশন না করে কেবল সেই ক্যোয়ারির জন্য সারি লক্ষ্যগুলির প্রভাব বন্ধ করে দেয় এবং সম্ভবত সবচেয়ে সহজ / সর্বাধিক প্রত্যক্ষ উপায় হবে।

যদি এই ইঙ্গিতটি যুক্ত করা আপনাকে অনুমতি ত্রুটি দেয় (এর জন্য প্রয়োজনীয় DBCC TRACEON), আপনি এটি পরিকল্পনা গাইড ব্যবহার করে প্রয়োগ করতে পারেন:

QUERYTRACEONস্প্যাগেটিডবা দ্বারা পরিকল্পনাগুলি গাইড ব্যবহার করে

... বা কেবল একটি সঞ্চিত পদ্ধতি ব্যবহার করুন:

কি অনুমতি QUERYTRACEONপ্রয়োজন? কেন্দ্র লিটল দ্বারা


3

এসকিউএল সার্ভারের নতুন সংস্করণগুলি অপ্টিমাইজার যখন সারি লক্ষ্য অপ্টিমাইজেশন প্রয়োগ করতে সক্ষম হয় তখন সাবওটিমাল পারফরম্যান্স পাওয়া প্রশ্নের সাথে ডিল করার জন্য বিভিন্ন (এবং তর্কযোগ্যভাবে আরও ভাল) বিকল্পগুলি সরবরাহ করে। এসকিউএল সার্ভার 2016 এসপি 1 এর পরিচয় দিয়েছে DISABLE_OPTIMIZER_ROWGOAL USE HINTযা ট্রেস ফ্ল্যাগ 4138 এর মতো একই প্রভাব রয়েছে you're আপনি যদি এই সংস্করণে না থাকেন তবে আপনি OPTIMIZE FORকেবল 1 এর পরিবর্তে সমস্ত সারিগুলি ফেরত দেওয়ার জন্য নকশা করা ক্যোয়ারী পরিকল্পনা পেতে ক্যোয়ারী ইঙ্গিতটি ব্যবহার করে বিবেচনা করতে পারেন below নীচের ক্যোয়ারী প্রশ্নের মত একই ফলাফলটি ফিরিয়ে দেবে তবে এটি কেবল 1 সারি পাওয়ার লক্ষ্য নিয়ে তৈরি করা হবে না।

DECLARE @top INT = 1;

SELECT TOP (@top) dc.DOCUMENT_ID,
        dc.COPIES,
        dc.REQUESTOR,
        dc.D_ID,
        cj.FILE_NUMBER
FROM DOCUMENT_QUEUE dc
JOIN CORRESPONDENCE_JOURNAL cj
    ON dc.DOCUMENT_ID = cj.DOCUMENT_ID
WHERE dc.QUEUE_DATE <= GETDATE()
  AND dc.PRINT_LOCATION = 2
ORDER BY cj.FILE_NUMBER
OPTION (OPTIMIZE FOR (@top = 987654321));

2

যেহেতু আপনি একটি করছেন TOP(1), তাই আমি ORDER BYএকটি শুরু করার জন্য নিয়ামবাদী করার পরামর্শ দিই । খুব কমপক্ষে এটি নিশ্চিত করবে যে ফলাফলগুলি কার্যকরীভাবে অনুমানযোগ্য (প্রতিরোধের পরীক্ষার জন্য সর্বদা দরকারী)। দেখে মনে হচ্ছে আপনি যোগ করতে হবে DC.D_IDএবং CJ.CORRESPONDENCE_IDযে জন্য।

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.