সারসংক্ষেপ
এসকিউএল সার্ভার সঠিক জোড় (অভ্যন্তরীণ বা বাহ্যিক) ব্যবহার করে এবং প্রয়োগ এবং যোগদানের মধ্যবর্তী অভ্যন্তরীণ অনুবাদগুলি সম্পাদন করার সময় মূল ক্যোয়ারীর সমস্ত শব্দার্থককে সম্মান করার জন্য প্রয়োজনীয় প্রজেকশন যুক্ত করে ।
পরিকল্পনাগুলির পার্থক্যগুলি সমস্ত এসকিউএল সার্ভারে একটি গ্রুপের সাথে এবং ছাড়াই সমষ্টিগুলির বিভিন্ন শব্দার্থক দ্বারা ব্যাখ্যা করা যেতে পারে ।
বিস্তারিত
বনাম প্রয়োগ প্রয়োগ করুন
আমাদের প্রয়োগ এবং যোগদানের মধ্যে পার্থক্য করতে সক্ষম হতে হবে :
প্রয়োগ করা
প্রয়োগের অভ্যন্তরীণ (নিম্ন) ইনপুটটি বহিরাগত (উপরের) ইনপুটটির প্রতিটি সারিটির জন্য চলমান রয়েছে, বর্তমান বহিরাগত সারি দ্বারা সরবরাহিত এক বা একাধিক অভ্যন্তরীণ পার্শ্বের মানগুলি। আবেদনের সামগ্রিক ফলাফলটি প্যারামিটারাইজড অভ্যন্তরীণ পাশের মৃত্যুদণ্ডগুলি দ্বারা উত্পাদিত সমস্ত সারিগুলির সংমিশ্রণ (সমস্ত ইউনিয়ন)। প্যারামিটারগুলির উপস্থিতি মানে প্রয়োগগুলি কখনও কখনও সংযুক্ত যোগ হিসাবে পরিচিত।
নেস্টেড লুপস অপারেটর দ্বারা প্রয়োগ প্রয়োগের পরিকল্পনায় সর্বদা একটি প্রয়োগ প্রয়োগ করা হয় । অপারেটরের পূর্বাভাসে যোগদানের পরিবর্তে আউটার রেফারেন্স সম্পত্তি থাকবে। বাহ্যিক রেফারেন্সগুলি লুপের প্রতিটি পুনরাবৃত্তির বাইরের দিক থেকে অভ্যন্তরীণ দিকে প্রেরণ করা প্যারামিটার।
যোগদান
একটি জোড় জোড় অপারেটরে তার যোগদানের প্রাকটিকাকে মূল্যায়ন করে। যোগদানটি সাধারণত হ্যাশ ম্যাচ , মার্জ বা এসকিউএল সার্ভারে নেস্টেড লুপস অপারেটর দ্বারা প্রয়োগ করা যেতে পারে ।
যখন নেস্টেড লুপগুলি বেছে নেওয়া হয়, তখন এটি আউটার রেফারেন্সের অভাবের দ্বারা প্রয়োগ (এবং সাধারণত একটি জয়েন্ট প্রিকেট উপস্থিতি) দ্বারা আলাদা করা যায় । একটি যোগদানের অভ্যন্তরীণ ইনপুট কখনই বাহ্যিক ইনপুট থেকে মানগুলি উল্লেখ করে না - অভ্যন্তরীণ দিকটি প্রতিটি বাহ্যিক সারির জন্য এখনও একবার কার্যকর করা হয় তবে অভ্যন্তরীণ পাশের মৃত্যুদণ্ডগুলি বর্তমান বাহ্যিক সারির কোনও মানগুলির উপর নির্ভর করে না।
আরো বিস্তারিত জানার জন্য দেখুন আমার পোস্টে প্রয়োগ বনাম নেস্টেড loops যোগদান ।
... সেখানে কেন হয় বাইরের পরিবর্তে একটি কার্যকর পরিকল্পনা যোগদান ভেতরের যোগদানের?
যখন কোনও সস্তা যোগ-ভিত্তিক পরিকল্পনার সন্ধান করতে পারে তা দেখার জন্য যখন অপ্টিমাইজার একটি জোড়কে (একটি নিয়ম বলে ) প্রয়োগ করার জন্য কোনও রূপান্তর করে তখন বাহ্যিক যোগদান শুরু হয় । একটি বাইরের হতে জন্য যোগ দিতে প্রয়োজন বোধ করা হয় যোগদান শুদ্ধি যখন প্রয়োগ একটি রয়েছে স্কালে সমষ্টিগত । একটি ভেতরের যোগদানের হবে না নিশ্চিত উত্পাদন করতে মূল হিসাবে একই ফলাফল প্রয়োগ হিসাবে আমরা দেখতে হবে।ApplyHandler
স্কেলার এবং ভেক্টর সমষ্টি
- সম্পর্কিত
GROUP BY
ধারা ছাড়া একটি সমষ্টি একটি স্কেলার সমষ্টি।
- সংশ্লিষ্ট
GROUP BY
অনুচ্ছেদের সমষ্টি একটি ভেক্টর সমষ্টি।
এসকিউএল সার্ভারে, স্কেলার সমষ্টি সর্বদা একটি সারি তৈরি করে, এমনকি যদি এটি সামগ্রিকভাবে কোনও সারি দেওয়া না হয়। উদাহরণস্বরূপ, COUNT
কোনও সারিগুলির স্কেলারের সমষ্টি শূন্য নয়। কোনও সারিগুলির একটি ভেক্টর COUNT
সমষ্টি হ'ল খালি সেট (কোনও সারি নেই)।
নিম্নলিখিত খেলনা ক্যোয়ারী পার্থক্য চিত্রিত করে। আপনি স্কেলার এবং ভেক্টর সমষ্টি সম্পর্কে আমার নিবন্ধ মজাতে স্কেলার এবং ভেক্টর সমষ্টি সম্পর্কে আরও পড়তে পারেন ।
-- Produces a single zero value
SELECT COUNT_BIG(*) FROM #MyTable AS MT WHERE 0 = 1;
-- Produces no rows
SELECT COUNT_BIG(*) FROM #MyTable AS MT WHERE 0 = 1 GROUP BY ();
ডিবি <> ফিডাল ডেমো
যোগদানের জন্য রূপান্তরকরণ প্রয়োগ করুন
আমি আগে উল্লেখ যোগদানের যে একটি বাইরের হতে প্রয়োজন বোধ করা হয় জন্য যোগ দিতে শুদ্ধি যখন মূল আবেদন একটি রয়েছে স্কালে সমষ্টিগত । কেন এটি বিশদে এই কেসটি তা দেখানোর জন্য, আমি প্রশ্ন জিজ্ঞাসার একটি সরলীকৃত উদাহরণ ব্যবহার করব:
DECLARE @A table (A integer NULL, B integer NULL);
DECLARE @B table (A integer NULL, B integer NULL);
INSERT @A (A, B) VALUES (1, 1);
INSERT @B (A, B) VALUES (2, 2);
SELECT * FROM @A AS A
CROSS APPLY (SELECT c = COUNT_BIG(*) FROM @B AS B WHERE B.A = A.A) AS CA;
কলামের জন্য সঠিক ফলাফলের c
হয় শূন্য , কারণ COUNT_BIG
একটি নয় স্কালে সমষ্টিগত। ফর্মটিতে যোগদানের জন্য এই প্রয়োগের ক্যোয়ারীটি অনুবাদ করার সময়, এসকিউএল সার্ভার একটি অভ্যন্তরীণ বিকল্প উত্পন্ন করে যা টি-এসকিউএল-এ প্রকাশ করা হলে নিম্নলিখিতগুলির মতো দেখাবে:
SELECT A.*, c = COALESCE(J1.c, 0)
FROM @A AS A
LEFT JOIN
(
SELECT B.A, c = COUNT_BIG(*)
FROM @B AS B
GROUP BY B.A
) AS J1
ON J1.A = A.A;
অসম্পর্কিত যোগদান হিসাবে প্রয়োগটি পুনরায় লেখার জন্য, আমাদের GROUP BY
উত্পন্ন টেবিলটিতে একটি প্রবর্তন করতে হবে (অন্যথায় A
যোগদানের জন্য কোনও কলাম থাকতে পারে না )। যোগদানটি একটি বাহ্যিক যোগ হতে হবে যাতে সারণী থেকে প্রতিটি সারি @A
আউটপুটটিতে একটি সারি উত্পাদন করতে থাকে। বাম যোগটি NULL
কলামের জন্য একটি তৈরি করবে c
যখন জোড়ের প্রাকটিকেট সত্য হিসাবে মূল্যায়ন করে না। যে NULL
চাহিদা দ্বারা শুন্যতে অনূদিত করা COALESCE
থেকে একটি সঠিক রূপান্তর সম্পূর্ণ করতে আবেদন ।
নীচের ডেমোটি দেখায় যে কীভাবে উভয় বাহ্যিক যোগদান এবং মূল প্রয়োগের ক্যোয়ারী হিসাবে যোগদানCOALESCE
করে একই ফলাফল উত্পাদন করতে হবে :
ডিবি <> ফিডাল ডেমো
সাথে GROUP BY
... কেন ধারা দ্বারা গ্রুপটিকে অসন্তুষ্ট করা তার অভ্যন্তরীণ যোগদানের ফলাফল করে?
সরলীকৃত উদাহরণ অবিরত করা, তবে একটি যুক্ত করা GROUP BY
:
DECLARE @A table (A integer NULL, B integer NULL);
DECLARE @B table (A integer NULL, B integer NULL);
INSERT @A (A, B) VALUES (1, 1);
INSERT @B (A, B) VALUES (2, 2);
-- Original
SELECT * FROM @A AS A
CROSS APPLY
(SELECT c = COUNT_BIG(*) FROM @B AS B WHERE B.A = A.A GROUP BY B.A) AS CA;
COUNT_BIG
এখন একটি হল ভেক্টর সমষ্টিগত, এটা, তাই একটি খালি ইনপুট সেট জন্য সঠিক ফলাফলের আর শূন্য হয় সব সময়ে কোন সারি । অন্য কথায়, উপরের স্টেটমেন্টগুলি চালানো কোনও আউটপুট তৈরি করে না।
যোগদানের জন্য প্রয়োগ থেকে অনুবাদ করার সময় এই শব্দার্থবিজ্ঞানগুলি সম্মানের পক্ষে অনেক সহজ , যেহেতু স্বাভাবিকভাবে কোনও বাহ্যিক সারি প্রত্যাখ্যান করে যা কোনও অভ্যন্তরের সারি সারি তৈরি করে না। অতএব আমরা কোনও অতিরিক্ত অভিব্যক্তি প্রক্ষেপণ ছাড়াই নিরাপদে এখন একটি অভ্যন্তরীণ যোগ দিন ব্যবহার করতে পারি:CROSS APPLY
-- Rewrite
SELECT A.*, J1.c
FROM @A AS A
JOIN
(
SELECT B.A, c = COUNT_BIG(*)
FROM @B AS B
GROUP BY B.A
) AS J1
ON J1.A = A.A;
নীচের ডেমোটি দেখায় যে অভ্যন্তরীণ যোগদানের পুনর্লিখনটি ভেক্টর সমষ্টিতে মূল প্রয়োগের সাথে একই ফলাফল তৈরি করে:
ডিবি <> ফিডাল ডেমো
অপ্টিমাইজারটি ছোট টেবিলের সাথে একত্রীকরণের অভ্যন্তরীণ যোগদানটি বেছে নেওয়ার জন্য ঘটায় কারণ এটি দ্রুত একটি সস্তা যোগদানের পরিকল্পনা খুঁজে পায় (যথেষ্ট ভাল পরিকল্পনা পাওয়া গেছে)। ব্যয়ভিত্তিক অপ্টিমাইজারটি প্রয়োগটিতে আবার যোগদানের পুনরায় লিখন করতে পারে - সম্ভবত একটি সস্তার প্রয়োগের পরিকল্পনা খুঁজে পেতে পারে, যেমন একটি লুপ জয়েন বা ফোর্সেক ইঙ্গিত ব্যবহার করা হয় তবে এটি এখানে কার্যকর হবে না - তবে এটি ক্ষেত্রে প্রচেষ্টাটির পক্ষে উপযুক্ত নয়।
মন্তব্য
সরলীকৃত উদাহরণগুলি আরও স্পষ্টভাবে অর্থগত পার্থক্যগুলি দেখানোর জন্য বিভিন্ন সামগ্রী সহ বিভিন্ন সারণী ব্যবহার করে।
যে কেউ তর্ক করতে পারে যে অপ্টিমাইজারটি কোনও স্ব-যোগদান সম্পর্কে কোনও যুক্তিযুক্ত (অ-যোগদানকারী) সারি তৈরি করতে সক্ষম না হওয়ার বিষয়ে যুক্তিযুক্ত হতে সক্ষম হওয়া উচিত, তবে এটিতে আজ সেই যুক্তিটি নেই। বিচ্ছিন্নতা স্তর এবং সমবর্তী ক্রিয়াকলাপের উপর নির্ভর করে কোনও ক্যোয়ারিতে একই টেবিলটি একাধিকবার অ্যাক্সেস করা সাধারণভাবে একই ফলাফল প্রদানের গ্যারান্টিযুক্ত নয়।
অপ্টিমাইজার এই শব্দার্থক এবং প্রান্তের মামলাগুলি সম্পর্কে উদ্বিগ্ন যাতে আপনার দরকার নেই।
বোনাস: অভ্যন্তরীণ প্রয়োগের পরিকল্পনা
এসকিউএল সার্ভার উদাহরণ ক্যোয়ারির জন্য একটি অভ্যন্তরীণ প্রয়োগ পরিকল্পনা (কোনও অভ্যন্তরীণ যোগদানের পরিকল্পনা নয়!) তৈরি করতে পারে , এটি কেবল ব্যয়বহুল কারণে না বেছে নেয়। প্রশ্নটিতে প্রদর্শিত বাইরের যোগদানের পরিকল্পনার দামটি আমার ল্যাপটপের এসকিউএল সার্ভার 2017 উদাহরণে 0.02898 ইউনিট।
আপনি অনাবৃত ও অসমর্থিত ট্রেস পতাকা 9114 (যা অক্ষম করে ইত্যাদি) কেবল উদাহরণের জন্য ব্যবহার করে একটি অ্যাপ্লিকেশন (পারস্পরিক সম্পর্কযুক্ত যোগ) জোর করতে পারেন ApplyHandler
:
SELECT *
FROM #MyTable AS mt
CROSS APPLY
(
SELECT COUNT_BIG(DISTINCT mt2.Col_B) AS dc
FROM #MyTable AS mt2
WHERE mt2.Col_A = mt.Col_A
--GROUP BY mt2.Col_A
) AS ca
OPTION (QUERYTRACEON 9114);
এটি একটি অলস সূচক স্পুল সহ একটি প্রয়োগ নেস্টেড লুপস পরিকল্পনা তৈরি করে । মোট আনুমানিক ব্যয় 0.0463983 (নির্বাচিত পরিকল্পনার চেয়ে বেশি):
নোটযুক্ত লুপগুলি প্রয়োগ করে কার্যকরকরণ পরিকল্পনাটি GROUP BY
ক্লজের উপস্থিতি নির্বিশেষে "অভ্যন্তরীণ যোগ" শব্দার্থক ব্যবহার করে সঠিক ফলাফল দেয় ।
সত্যিকারের বিশ্বে, এসকিউএল সার্ভারকে প্রাকৃতিকভাবে এই বিকল্পটি বেছে নিতে উত্সাহিত করার জন্য আবেদনের অভ্যন্তরীণ দিকের অন্বেষণকে সমর্থন করার জন্য আমাদের সাধারণত একটি সূচক থাকে example
CREATE INDEX i ON #MyTable (Col_A, Col_B);
ডিবি <> ফিডাল ডেমো