শুরু করার জন্য আমি একটি উত্তর পোস্ট করব। আমার প্রথম চিন্তাটি ছিল যে প্রতিটি অক্ষরের জন্য একটি সারি রয়েছে এমন কয়েকটি সহায়ক টেবিলের সাথে নেস্টেড লুপের ক্রম-সংরক্ষণের প্রকৃতির সুযোগ নেওয়া সম্ভব হবে। জটিল অংশটি এমনভাবে লুপিং করতে চলেছিল যাতে ফলাফলগুলি দৈর্ঘ্যের পাশাপাশি ডুপ্লিকেটগুলি এড়িয়ে চলা অর্ডার করে। উদাহরণস্বরূপ, যখন '' এর সাথে সমস্ত 26 টি মূলধনী অন্তর্ভুক্ত কোনও সিটিইতে যোগ দেওয়ার সময়, আপনি উত্পন্ন করতে পারেন 'A' + '' + 'A'এবং '' + 'A' + 'A'এটি অবশ্যই একই স্ট্রিং।
প্রথম সিদ্ধান্তটি ছিল হেল্পার ডেটা কোথায় সঞ্চয় করা যায়। আমি একটি টেম্প টেবিলটি ব্যবহার করার চেষ্টা করেছি তবে ডেটা একক পৃষ্ঠায় ফিট করার পরেও এটির পারফরম্যান্সে আশ্চর্যজনকভাবে নেতিবাচক প্রভাব পড়ে। টেম্প টেবিলটিতে নীচের ডেটা রয়েছে:
SELECT 'A'
UNION ALL SELECT 'B'
...
UNION ALL SELECT 'Y'
UNION ALL SELECT 'Z'
কোনও সিটিই ব্যবহারের তুলনায়, ক্লোস্টারযুক্ত টেবিলের সাথে ক্যোয়ারীটি 3X দীর্ঘ এবং একটি স্তূপ সহ 4X দীর্ঘ সময় নিয়েছে। আমি বিশ্বাস করি না যে সমস্যাটি হ'ল ডেটা ডিস্কে রয়েছে। এটি একটি একক পৃষ্ঠা হিসাবে মেমরিতে পড়তে হবে এবং পুরো পরিকল্পনার জন্য মেমরিতে প্রক্রিয়া করা উচিত। সাধারণত এসকিউএল সার্ভার সাধারণত কনস্ট্যান্ট স্ক্যান অপারেটরের ডেটা দিয়ে সাধারণত রোউস্টোর পৃষ্ঠাগুলিতে সঞ্চিত ডেটার সাথে আরও দক্ষতার সাথে কাজ করতে পারে।
মজার বিষয় হচ্ছে, এসকিউএল সার্ভার একটি একক পৃষ্ঠার টেম্পডিবি টেবিল থেকে আদেশিত ফলাফলগুলি একটি টেবিল স্পুলে অর্ডার করা ডেটা সহ চয়ন করতে পছন্দ করে:

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

তবে কোনও সম্ভাবনা না নেওয়াই ভাল, বিশেষত যদি কোনও বড় পারফরম্যান্স ওভারহেড ছাড়াই এটি করার উপায় থাকে। একটি অতিমাত্রায় TOPঅপারেটর যুক্ত করে কোনও উত্পন্ন টেবিলে ডেটা অর্ডার করা সম্ভব । উদাহরণ স্বরূপ:
(SELECT TOP (26) CHR FROM FIRST_CHAR ORDER BY CHR)
ক্যোয়ারির সাথে যুক্ত হওয়াতে গ্যারান্টি দেওয়া উচিত যে ফলাফলগুলি সঠিক ক্রমে ফিরে আসবে। আমি প্রত্যাশা করেছি সমস্ত প্রকারেরই একটি বড় নেতিবাচক কর্মক্ষমতা প্রভাব ফেলবে। ক্যোয়ারী অপ্টিমাইজারটি আনুমানিক ব্যয়ের ভিত্তিতে এটিও প্রত্যাশা করেছিল:

খুব আশ্চর্যের বিষয়, আমি সিপিইউ সময় বা রানটাইমের কোনও স্পষ্ট ক্রম ছাড়াই বা ছাড়াই কোনও পরিসংখ্যানগতভাবে উল্লেখযোগ্য পার্থক্যটি পর্যবেক্ষণ করতে পারিনি। যদি কিছু থাকে তবে ক্যোয়ারীটি মনে হচ্ছে দ্রুতগতিতে চলেছে ORDER BY! এই আচরণ সম্পর্কে আমার কোনও ব্যাখ্যা নেই।
সমস্যার জটিল অংশটি ছিল সঠিক স্থানগুলিতে ফাঁকা অক্ষরগুলি কীভাবে সন্নিবেশ করা যায় তা নির্ধারণ করা। যেমন আগে উল্লেখ করা হয়েছে CROSS JOINতার ফলে সদৃশ ডেটা হবে। আমরা জানি যে 100000000 তম স্ট্রিংটির দৈর্ঘ্যের ছয়টি অক্ষর থাকবে কারণ:
26 + 26 ^ 2 + 26 ^ 3 + 26 ^ 4 + 26 ^ 5 = 914654 <100000000
কিন্তু
26 + 26 ^ 2 + 26 ^ 3 + 26 ^ 4 + 26 ^ 5 + 26 ^ 6 = 321272406> 100000000
সুতরাং আমাদের কেবল ছয়বার সিটিই লেটারে যোগ দিতে হবে। মনে করুন যে আমরা ছয়বার সিটিইতে যোগ দিয়েছি, প্রতিটি সিটিই থেকে একটি করে চিঠি নিয়েছি এবং সেগুলি সমস্তকে একত্রে সম্মতি জানাই। মনে করুন বামতম অক্ষরটি ফাঁকা নয়। যদি পরবর্তী কোনও অক্ষর ফাঁকা থাকে তার মানে স্ট্রিংটি ছয় অক্ষরের চেয়ে কম লম্বা তাই এটি একটি সদৃশ। সুতরাং, আমরা প্রথম অ-ফাঁকা অক্ষর খুঁজে পেয়ে এবং নকলগুলি ফাঁকা না হওয়ার পরে সমস্ত অক্ষরের প্রয়োজনের মাধ্যমে নকলগুলি প্রতিরোধ করতে পারি। আমি FLAGসিটিইর মধ্যে একটিতে একটি কলাম বরাদ্দ করে এবং ধারাটিতে একটি চেক যুক্ত করে এটি ট্র্যাক করা বেছে নিয়েছি WHERE। কোয়েরিটি দেখার পরে এটি আরও স্পষ্ট হওয়া উচিত। চূড়ান্ত ক্যোয়ারী নিম্নরূপ:
WITH FIRST_CHAR (CHR) AS
(
SELECT 'A'
UNION ALL SELECT 'B'
UNION ALL SELECT 'C'
UNION ALL SELECT 'D'
UNION ALL SELECT 'E'
UNION ALL SELECT 'F'
UNION ALL SELECT 'G'
UNION ALL SELECT 'H'
UNION ALL SELECT 'I'
UNION ALL SELECT 'J'
UNION ALL SELECT 'K'
UNION ALL SELECT 'L'
UNION ALL SELECT 'M'
UNION ALL SELECT 'N'
UNION ALL SELECT 'O'
UNION ALL SELECT 'P'
UNION ALL SELECT 'Q'
UNION ALL SELECT 'R'
UNION ALL SELECT 'S'
UNION ALL SELECT 'T'
UNION ALL SELECT 'U'
UNION ALL SELECT 'V'
UNION ALL SELECT 'W'
UNION ALL SELECT 'X'
UNION ALL SELECT 'Y'
UNION ALL SELECT 'Z'
)
, ALL_CHAR (CHR, FLAG) AS
(
SELECT '', 0 CHR
UNION ALL SELECT 'A', 1
UNION ALL SELECT 'B', 1
UNION ALL SELECT 'C', 1
UNION ALL SELECT 'D', 1
UNION ALL SELECT 'E', 1
UNION ALL SELECT 'F', 1
UNION ALL SELECT 'G', 1
UNION ALL SELECT 'H', 1
UNION ALL SELECT 'I', 1
UNION ALL SELECT 'J', 1
UNION ALL SELECT 'K', 1
UNION ALL SELECT 'L', 1
UNION ALL SELECT 'M', 1
UNION ALL SELECT 'N', 1
UNION ALL SELECT 'O', 1
UNION ALL SELECT 'P', 1
UNION ALL SELECT 'Q', 1
UNION ALL SELECT 'R', 1
UNION ALL SELECT 'S', 1
UNION ALL SELECT 'T', 1
UNION ALL SELECT 'U', 1
UNION ALL SELECT 'V', 1
UNION ALL SELECT 'W', 1
UNION ALL SELECT 'X', 1
UNION ALL SELECT 'Y', 1
UNION ALL SELECT 'Z', 1
)
SELECT TOP (100000000)
d6.CHR + d5.CHR + d4.CHR + d3.CHR + d2.CHR + d1.CHR
FROM (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d6
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d5
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d4
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d3
CROSS JOIN (SELECT TOP (27) FLAG, CHR FROM ALL_CHAR ORDER BY CHR) d2
CROSS JOIN (SELECT TOP (26) CHR FROM FIRST_CHAR ORDER BY CHR) d1
WHERE (d2.FLAG + d3.FLAG + d4.FLAG + d5.FLAG + d6.FLAG) =
CASE
WHEN d6.FLAG = 1 THEN 5
WHEN d5.FLAG = 1 THEN 4
WHEN d4.FLAG = 1 THEN 3
WHEN d3.FLAG = 1 THEN 2
WHEN d2.FLAG = 1 THEN 1
ELSE 0 END
OPTION (MAXDOP 1, FORCE ORDER, LOOP JOIN, NO_PERFORMANCE_SPOOL);
উপরে বর্ণিত হিসাবে সিটিইগুলি রয়েছে। ALL_CHARএতে পাঁচবার যোগ দেওয়া হয়েছে কারণ এতে ফাঁকা চরিত্রের জন্য একটি সারি অন্তর্ভুক্ত রয়েছে। স্ট্রিংয়ের চূড়ান্ত অক্ষরটি কখনই ফাঁকা হওয়া উচিত নয় সুতরাং এর জন্য একটি পৃথক সিটিই সংজ্ঞায়িত করা হয় FIRST_CHAR,। ALL_CHARউপরে বর্ণিত ডুপ্লিকেটগুলি প্রতিরোধ করতে অতিরিক্ত ফ্ল্যাগ কলামটি ব্যবহৃত হয়। এই চেকটি করার আরও বেশি কার্যকর উপায় থাকতে পারে তবে এটি করার আরও কার্যকর উপায় রয়েছে। সঙ্গে আমার দ্বারা আর একটি প্রচেষ্টা LEN()এবং POWER()বর্তমান সংস্করণের তুলনায় ছয় বার ধীর ক্যোয়ারী রান করেন।
MAXDOP 1এবং FORCE ORDERনির্দেশ নিশ্চিত, যাতে ক্যোয়ারীতে সংরক্ষিত আছে করতে অপরিহার্য। একটি টীকায়িত আনুমানিক পরিকল্পনাটি কেন তাদের বর্তমান ক্রমে যোগদান করে তা দেখতে সহায়ক হতে পারে:

অনুসন্ধানের পরিকল্পনাগুলি প্রায়শই ডান থেকে বামে পড়ে থাকে তবে সারি অনুরোধগুলি বাম থেকে ডানে ঘটে। আদর্শভাবে, এসকিউএল সার্ভার d1ধ্রুবক স্ক্যান অপারেটর থেকে 100 মিলিয়ন সারি অনুরোধ করবে । আপনি বাম থেকে ডানে সরানোর সময় আমি প্রতিটি অপারেটরের কাছ থেকে কম সারিগুলির অনুরোধ করার প্রত্যাশা করি। আমরা এটি বাস্তব বাস্তবায়ন পরিকল্পনায় দেখতে পাচ্ছি । অতিরিক্ত হিসাবে, নীচে এসকিউএল সেন্ট্রি প্ল্যান এক্সপ্লোরারের একটি স্ক্রিনশট রয়েছে:

আমরা ডি 1 থেকে হ'ল 100 মিলিয়ন সারি পেয়েছি যা একটি ভাল জিনিস। নোট করুন যে ডি 2 এবং ডি 3 এর মধ্যে সারিগুলির অনুপাত প্রায় 27: 1 (165336 * 27 = 4464072) যা ক্রস জয়েন কীভাবে কাজ করবে সে সম্পর্কে যদি আপনি চিন্তা করেন তবে তা বোধগম্য হয়। ডি 1 এবং ডি 2 এর মধ্যে সারিগুলির অনুপাত 22.4 যা কিছু নষ্ট কাজের প্রতিনিধিত্ব করে। আমি বিশ্বাস করি যে অতিরিক্ত সারিগুলি সদৃশগুলি (স্ট্রিংগুলির মাঝখানে ফাঁকা অক্ষরের কারণে) থেকে এসেছে যা এটিকে নেস্টেড লুপ জোড় অপারেটর দ্বারা ছাঁটাই করে না যা ফিল্টারিং করে।
LOOP JOINকারণ একটি ইঙ্গিতটি টেকনিক্যালি অপ্রয়োজনীয় CROSS JOINকরতে পারেন শুধুমাত্র একটি লুপ হিসাবে প্রয়োগ করা যেতে SQL সার্ভার যোগ। NO_PERFORMANCE_SPOOLঅপ্রয়োজনীয় টেবিল স্পুলিং প্রতিরোধ করা হয়। স্পুল ইঙ্গিত ছাড়াই ক্যোরিটিকে আমার মেশিনে 3 এক্স বেশি সময় লাগবে।
চূড়ান্ত ক্যোয়ারিতে সিপিইউ সময় প্রায় 17 সেকেন্ড এবং সর্বমোট 18 সেকেন্ডের সময় অতিবাহিত হয়। এসএসএমএসের মাধ্যমে ক্যোয়ারী চালানো এবং ফলাফল সেটটি বাতিল করার সময় এটি ছিল। আমি ডেটা তৈরির অন্যান্য পদ্ধতিগুলি দেখতে খুব আগ্রহী।