আমরা কি কিছু ভুল করছি বা এটি এসকিউএল সার্ভারের ত্রুটি?
এটি একটি ভুল-ফলাফলের বাগ, যা আপনার নিজের স্বাভাবিক সমর্থন চ্যানেলের মাধ্যমে প্রতিবেদন করা উচিত। যদি আপনার কাছে কোনও সহায়তা চুক্তি না থাকে তবে মাইক্রোসফ্ট যদি বাগ হিসাবে আচরণটি নিশ্চিত করে তবে অর্থ প্রদানের ঘটনাগুলি সাধারণত ফেরত দেওয়া হয় তা জানতে সহায়তা করতে পারে ।
বাগের জন্য তিনটি উপাদান প্রয়োজন:
- বাইরের রেফারেন্স সহ নেস্টেড লুপস (একটি প্রয়োগ)
- একটি অভ্যন্তরীণ দিকের অলস সূচক স্পুল যা বাইরের রেফারেন্সটি অনুসন্ধান করে
- একটি অভ্যন্তরীণ দিকের কনটেনটেশন অপারেটর
উদাহরণস্বরূপ, প্রশ্নের ক্যোয়ারী নিম্নলিখিতগুলির মতো একটি পরিকল্পনা তৈরি করে:
এই উপাদানগুলির মধ্যে একটি অপসারণের অনেকগুলি উপায় রয়েছে, তাই বাগটি আর পুনরুত্পাদন করে না।
উদাহরণস্বরূপ, কেউ সূচক বা পরিসংখ্যান তৈরি করতে পারে যার অর্থ অপটিমাইজার একটি অলস সূচক স্পুলটি ব্যবহার না করা বেছে নেয়। বা, কেউ হ্যাশকে জোর করতে ইঙ্গিতগুলি ব্যবহার করতে বা কনক্যাটেনেশন ব্যবহারের পরিবর্তে ইউনিয়নটিকে মার্জ করার জন্য ব্যবহার করতে পারে। একই শব্দার্থকতা প্রকাশ করতে কেউ আবার ক্যোয়ারীটিও আবার লিখতে পারে, তবে যার ফলশ্রুতিতে ভিন্ন পরিকল্পনার আকার আসে যেখানে এক বা একাধিক প্রয়োজনীয় উপাদান অনুপস্থিত থাকে।
আরো বিস্তারিত
একটি অলস সূচক স্পল অলসভাবে বাইরের রেফারেন্স (সম্পর্কিত প্যারামিটার) মান দ্বারা সূচিত একটি কাজের টেবিলে অভ্যন্তরীণ ফলাফলের সারিগুলিকে ক্যাশে করে। যদি কোনও অলস সূচক স্পুলটি এর আগে দেখা কোনও বাহ্যিক রেফারেন্সের জন্য জিজ্ঞাসা করা হয় তবে এটি তার কাজের সারণী (একটি "রিওয়াইন্ড") থেকে ক্যাশেড ফলাফল সারিটি নিয়ে আসে। যদি স্পুলটিকে বাইরের রেফারেন্স মানটির জন্য জিজ্ঞাসা করা হয় যা এটি আগে দেখা যায়নি, তবে এটি বর্তমান বাহ্যিক রেফারেন্স মানের সাথে তার সাবট্রি চালায় এবং ফলাফলটিকে (একটি "পুনরায় প্রত্যাবর্তন") ক্যাশে করে। অলস সূচক স্পুলের সন্ধানটি তার কাজের টেবিলের কী (গুলি) নির্দেশ করে।
এই নির্দিষ্ট পরিকল্পনার আকারে সমস্যাটি দেখা দেয় যখন স্পুল পরীক্ষা করে দেখেছিল যে কোনও নতুন বহিরাগত রেফারেন্সটি আগে দেখা একইরকম কিনা। নেস্টেড লুপস যোগ দিন এর বাইরের রেফারেন্সগুলি সঠিকভাবে আপডেট করে এবং অপারেটরদের তাদের PrepRecompute
ইন্টারফেস পদ্ধতির মাধ্যমে তার অভ্যন্তরীণ ইনপুটটিতে অবহিত করে। এই চেকের শুরুতে, অভ্যন্তরীণ পার্শ্ব অপারেটররা CParamBounds:FNeedToReload
শেষবারের চেয়ে বাইরের রেফারেন্সটি পরিবর্তিত হয়েছে কিনা তা দেখতে সম্পত্তিটি পড়েন । স্ট্যাকের একটি উদাহরণ নীচে দেখানো হয়েছে:
CParamBounds:FNeedToReload
বাহ্যিক রেফারেন্স আসলেই বদলেছে কিনা তা নির্বিশেষে উপরের দেখানো সাবট্রিটি যখন উপস্থিত রয়েছে, বিশেষত যেখানে কনটেনটেশন ব্যবহার করা হয়, তখন কিছু ভুল হয় (সম্ভবত একটি বাইওয়াল / বাইআরফ / কপি সমস্যা) যা সর্বদা মিথ্যা দেয়।
যখন একই সাবট্রি উপস্থিত থাকে তবে একটি মার্জ ইউনিয়ন বা হ্যাশ ইউনিয়ন ব্যবহার করা হয়, প্রতিটি প্রয়োজনীয়তার ক্ষেত্রে এই প্রয়োজনীয় সম্পত্তিটি সঠিকভাবে সেট করা থাকে এবং অলস সূচক স্পুল প্রতিটি সময় যথাযথভাবে পুনরায় সংশোধন বা পুনঃনির্মাণ করে। বিচ্ছিন্ন বাছাই এবং প্রবাহ সমষ্টি উপায় দ্বারা, দোষহীন are আমার সন্দেহ হ'ল মার্জ এবং হ্যাশ ইউনিয়ন আগের মানটির একটি অনুলিপি তৈরি করে, যেখানে কনক্যাটেনেশন একটি রেফারেন্স ব্যবহার করে। দুর্ভাগ্যক্রমে, এসকিউএল সার্ভার উত্স কোড অ্যাক্সেস না করে এটি যাচাই করা প্রায় অসম্ভব।
নেট ফলাফলটি হ'ল সমস্যাযুক্ত পরিকল্পনার আকারের অলস সূচক স্পুল সর্বদা মনে করে যে এটি ইতিমধ্যে বর্তমান বাহ্যিক রেফারেন্সটি দেখে ফেলেছে, তার কাজের সারণীতে সন্ধান করে পুনরায় রাইন্ড করে, সাধারণত কিছুই খুঁজে পায় না, সুতরাং বাহ্যিক রেফারেন্সের জন্য কোনও সারি ফিরে আসে না। একটি ডিবাগারে মৃত্যুদন্ড কার্যকর করার সময়, স্পুল কেবল কখনও তার RewindHelper
পদ্ধতিটি চালায় এবং কখনও তার ReloadHelper
পদ্ধতি (পুনরায় লোড = এই প্রসঙ্গে পুনরায় প্রত্যাবর্তন) করে না। এটি কার্যকর করার পরিকল্পনায় স্পষ্ট হয় কারণ স্পুলের অধীনে অপারেটরদের সকলের 'মৃত্যুর সংখ্যা = 1' থাকে।
ব্যতিক্রম অবশ্যই, অলস সূচক স্পুল প্রদত্ত প্রথম বাহ্যিক রেফারেন্সের জন্য। এটি সর্বদা সাবট্রি চালায় এবং কাজের সারণীতে ফলাফলের সারিটি ক্যাশে করে। পরবর্তী সমস্ত পুনরাবৃত্তির ফলস্বরূপ একটি রিওয়াইন্ড তৈরি হয়, যা কেবলমাত্র একটি সারি (একক ক্যাশেড সারি) উত্পাদন করে যখন বর্তমান পুনরাবৃত্তিটি প্রথমবারের মতো বাইরের রেফারেন্সের জন্য একই মান রাখে।
সুতরাং, নেস্টেড লুপস জোনের বাইরের দিকে যে কোনও প্রদত্ত ইনপুট সেট করার জন্য, প্রথম সারির ডুপ্লিকেটগুলি প্রক্রিয়াযুক্ত হওয়াতে কোয়েরিটি যতগুলি সারি ফিরে আসবে (অবশ্যই প্রথম সারির জন্য প্লাস ওয়ান)।
ডেমো
সারণী এবং নমুনা ডেটা:
CREATE TABLE #T1
(
pk integer IDENTITY NOT NULL,
c1 integer NOT NULL,
CONSTRAINT PK_T1
PRIMARY KEY CLUSTERED (pk)
);
GO
INSERT #T1 (c1)
VALUES
(1), (2), (3), (4), (5), (6),
(1), (2), (3), (4), (5), (6),
(1), (2), (3), (4), (5), (6);
নিম্নলিখিত (তুচ্ছ) কোয়েরিটি মার্জ ইউনিয়ন ব্যবহার করে প্রতিটি সারির (মোট 18 টি) জন্য সঠিক দুটি গণনা তৈরি করে:
SELECT T1.c1, C.c1
FROM #T1 AS T1
CROSS APPLY
(
SELECT COUNT_BIG(*) AS c1
FROM
(
SELECT T1.c1
UNION
SELECT NULL
) AS U
) AS C;
যদি আমরা এখন একটি জোটকে জোর করার জন্য একটি কোয়েরি ইঙ্গিতটি যুক্ত করি:
SELECT T1.c1, C.c1
FROM #T1 AS T1
CROSS APPLY
(
SELECT COUNT_BIG(*) AS c1
FROM
(
SELECT T1.c1
UNION
SELECT NULL
) AS U
) AS C
OPTION (CONCAT UNION);
সম্পাদন পরিকল্পনার সমস্যাযুক্ত আকার রয়েছে:
এবং ফলাফলটি এখন ভুল, মাত্র তিনটি সারি:
যদিও এই আচরণের গ্যারান্টি নেই তবে ক্লাস্টারড ইনডেক্স স্ক্যানের প্রথম সারির c1
মান 1 রয়েছে। এই মান সহ আরও দুটি সারি রয়েছে, সুতরাং মোট তিনটি সারি উত্পাদিত হয়।
এখন ডেটা টেবিলটি কেটে নিন এবং এটি 'প্রথম' সারির আরও নকল সহ লোড করুন:
TRUNCATE TABLE #T1;
INSERT #T1 (c1)
VALUES
(1), (2), (3), (4), (5), (6),
(1), (2), (3), (4), (5), (6),
(1), (1), (1), (1), (1), (1);
এখন কনেকেটেনশন পরিকল্পনাটি হ'ল:
এবং যেমন ইঙ্গিত করা হয়েছে, 8 টি সারি c1 = 1
অবশ্যই প্রস্তুত করা হয়:
আমি লক্ষ্য করেছি যে আপনি এই বাগের জন্য একটি কানেক্ট আইটেমটি খোলেন তবে বাস্তবে কোনও প্রভাব রয়েছে এমন সমস্যাগুলির প্রতিবেদন করার জায়গা এটি নয়। যদি এটি হয় তবে আপনার মাইক্রোসফ্ট সাপোর্টের সাথে যোগাযোগ করা উচিত।
এই ভুল-ফলাফল বাগটি কোনও পর্যায়ে স্থির হয়েছিল। এটি আর 2012 থেকে এসকিউএল সার্ভারের কোনও সংস্করণে আমার জন্য পুনরুত্পাদন করে না। এটি এসকিউএল সার্ভার 2008 আর 2 এসপি 3-জিডিআর বিল্ড 10.50.6560.0 (এক্স 64) এ রিপ্রো করে।