ক্রস প্রয়োগ করে বাহ্যিক যোগদানের উত্পাদন করে


17

এসকিউএলকে পার্টিশন নিয়ে আলাদা গণনা করার উত্তরে এরিক ডার্লিং এই কোডটি অভাবের জন্য কাজ করতে পোস্ট করেছেন COUNT(DISTINCT) OVER ():

SELECT      *
FROM        #MyTable AS mt
CROSS APPLY (   SELECT COUNT(DISTINCT mt2.Col_B) AS dc
                FROM   #MyTable AS mt2
                WHERE  mt2.Col_A = mt.Col_A
                -- GROUP BY mt2.Col_A 
            ) AS ca;

কোয়েরিটি ব্যবহার করে CROSS APPLY(না OUTER APPLY) তবে কেন অভ্যন্তরীণ যোগদানের পরিবর্তে এক্সিকিউশন প্ল্যানে কোনও বহিরাগত যোগদান রয়েছে ?

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

এছাড়াও দলটিকে ক্লজ দ্বারা সংঘাতবদ্ধ করার ফলে কেন একটি অভ্যন্তরীণ যোগদানের ফলাফল হয়?

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

আমি মনে করি না যে ডেটা গুরুত্বপূর্ণ, তবে অন্য প্রশ্নে কেভিনহ্যাটসের দেওয়া কপিটি অনুলিপি করে:

create table #MyTable (
Col_A varchar(5),
Col_B int
)

insert into #MyTable values ('A',1)
insert into #MyTable values ('A',1)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',2)
insert into #MyTable values ('A',3)

insert into #MyTable values ('B',4)
insert into #MyTable values ('B',4)
insert into #MyTable values ('B',5)

উত্তর:


23

সারসংক্ষেপ

এসকিউএল সার্ভার সঠিক জোড় (অভ্যন্তরীণ বা বাহ্যিক) ব্যবহার করে এবং প্রয়োগ এবং যোগদানের মধ্যবর্তী অভ্যন্তরীণ অনুবাদগুলি সম্পাদন করার সময় মূল ক্যোয়ারীর সমস্ত শব্দার্থককে সম্মান করার জন্য প্রয়োজনীয় প্রজেকশন যুক্ত করে

পরিকল্পনাগুলির পার্থক্যগুলি সমস্ত এসকিউএল সার্ভারে একটি গ্রুপের সাথে এবং ছাড়াই সমষ্টিগুলির বিভিন্ন শব্দার্থক দ্বারা ব্যাখ্যা করা যেতে পারে ।


বিস্তারিত

বনাম প্রয়োগ প্রয়োগ করুন

আমাদের প্রয়োগ এবং যোগদানের মধ্যে পার্থক্য করতে সক্ষম হতে হবে :

  • প্রয়োগ করা

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

    নেস্টেড লুপস অপারেটর দ্বারা প্রয়োগ প্রয়োগের পরিকল্পনায় সর্বদা একটি প্রয়োগ প্রয়োগ করা হয় । অপারেটরের পূর্বাভাসে যোগদানের পরিবর্তে আউটার রেফারেন্স সম্পত্তি থাকবে। বাহ্যিক রেফারেন্সগুলি লুপের প্রতিটি পুনরাবৃত্তির বাইরের দিক থেকে অভ্যন্তরীণ দিকে প্রেরণ করা প্যারামিটার।

  • যোগদান

    একটি জোড় জোড় অপারেটরে তার যোগদানের প্রাকটিকাকে মূল্যায়ন করে। যোগদানটি সাধারণত হ্যাশ ম্যাচ , মার্জ বা এসকিউএল সার্ভারে নেস্টেড লুপস অপারেটর দ্বারা প্রয়োগ করা যেতে পারে ।

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

আরো বিস্তারিত জানার জন্য দেখুন আমার পোস্টে প্রয়োগ বনাম নেস্টেড 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);

ডিবি <> ফিডাল ডেমো


-3

ক্রস প্রয়োগ হ'ল ডেটাতে একটি লজিকাল অপারেশন। কীভাবে সেই ডেটা পাবেন তা সিদ্ধান্ত নেওয়ার সময় এসকিউএল সার্ভার আপনার পছন্দসই ডেটা পেতে উপযুক্ত শারীরিক অপারেটরটি চয়ন করে।

কোনও শারীরিক প্রয়োগ অপারেটর নেই এবং এসকিউএল সার্ভার এটিকে উপযুক্ত এবং আশাবাদী দক্ষ জোড় অপারেটরে অনুবাদ করে।

আপনি নীচের লিঙ্কে শারীরিক অপারেটরগুলির একটি তালিকা পেতে পারেন।

https://docs.microsoft.com/en-us/sql/relational-databases/showplan-logical-and-physical-operators-reference?view=sql-server-2017

লজিকাল অপারেটর সমন্বিত একটি ট্রি হিসাবে ক্যোয়ারী অপ্টিমাইজার একটি ক্যোয়ারী প্ল্যান তৈরি করে। ক্যোয়ারী অপ্টিমাইজার পরিকল্পনা তৈরির পরে, ক্যোয়ারী অপ্টিমাইজার প্রতিটি লজিকাল অপারেটরের জন্য সবচেয়ে দক্ষ শারীরিক অপারেটর চয়ন করে। কোন শারীরিক অপারেটর একটি লজিকাল অপারেটর বাস্তবায়ন করবে তা নির্ধারণের জন্য ক্যোয়ারী অপ্টিমাইজারটি ব্যয় ভিত্তিক পদ্ধতির ব্যবহার করে।

সাধারণত, একটি যৌক্তিক অপারেশন একাধিক শারীরিক অপারেটর দ্বারা প্রয়োগ করা যেতে পারে। তবে, বিরল ক্ষেত্রে, একটি শারীরিক অপারেটর একাধিক লজিকাল অপারেশনগুলিও প্রয়োগ করতে পারে।

সম্পাদনা / মনে হচ্ছে আপনার প্রশ্নটি আমি ভুল বুঝতে পেরেছি। এসকিউএল সার্ভার সাধারণত সবচেয়ে উপযুক্ত অপারেটরটি বেছে নেবে। আপনার ক্রোয়াকে উভয় টেবিলের সমস্ত সংমিশ্রণের জন্য মানগুলি ফেরত দেওয়ার দরকার নেই যা যখন ক্রস জয়েন ব্যবহৃত হবে। প্রতিটি সারিটির জন্য আপনি যে মানটি চান তা গণনা করা যা এখানে করা হয়।

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