সম্পূর্ণতার জন্য অন্য উপায় এই সমস্যা কাছে ব্যবহার করা বাহ্য প্রযোজ্য । আমাদের OUTER APPLY
প্রতিটি স্বতন্ত্র মানের জন্য অপারেটর যুক্ত করতে পারি যা আমাদের সন্ধান করতে হবে। এটি ইপারকিউবের পুনরাবৃত্তির পদ্ধতির মত ধারণার অনুরূপ, তবে কার্যকরভাবে পুনরাবৃত্তিটি হাতে লেখা রয়েছে। এর একটি সুবিধা হ'ল আমরা কর্মক্ষেত্রের TOP
পরিবর্তে উত্সযুক্ত টেবিলগুলিতে ব্যবহার করতে সক্ষম ROW_NUMBER()
। একটি বড় অসুবিধা হ'ল ক্যোরির পাঠ্য N
বাড়ার সাথে সাথে দীর্ঘ হয় ।
স্তূপের বিরুদ্ধে ক্যোয়ারির জন্য এখানে একটি প্রয়োগকরণ রয়েছে:
SELECT VAL
FROM (
SELECT t1.VAL VAL1, t2.VAL VAL2, t3.VAL VAL3, t4.VAL VAL4, t5.VAL VAL5, t6.VAL VAL6, t7.VAL VAL7, t8.VAL VAL8, t9.VAL VAL9, t10.VAL VAL10
FROM
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP
) t1
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t2 WHERE t2.VAL NOT IN (t1.VAL)
) t2
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t3 WHERE t3.VAL NOT IN (t1.VAL, t2.VAL)
) t3
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t4 WHERE t4.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL)
) t4
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t5 WHERE t5.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL)
) t5
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t6 WHERE t6.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL)
) t6
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t7 WHERE t7.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL)
) t7
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t8 WHERE t8.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL, t7.VAL)
) t8
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t9 WHERE t9.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL, t7.VAL, t8.VAL)
) t9
OUTER APPLY
(
SELECT TOP 1 VAL FROM X_10_DISTINCT_HEAP t10 WHERE t10.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL, t7.VAL, t8.VAL, t9.VAL)
) t10
) t
UNPIVOT
(
VAL FOR VALS IN (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL8, VAL9, VAL10)
) AS upvt;
উপরের ক্যোয়ারির জন্য প্রকৃত ক্যোয়ারী পরিকল্পনা এখানে । আমার মেশিনে এই কোয়েরিটি সিপিইউয়ের 625 এমএস এবং 12605 লজিকাল রিডের সাথে 713 এমএসে সম্পূর্ণ হয়। আমরা প্রতি 100 কে সারিতে একটি নতুন স্বতন্ত্র মান পাই তাই আমি এই কোয়েরিটি প্রায় 900000 * 10 * 0.5 = 4500000 সারি স্ক্যান করে আশা করব। তাত্ত্বিকভাবে এই কোয়েরিটি অন্য উত্তর থেকে এই কোয়েরিটির পাঁচবার যৌক্তিক পাঠ করা উচিত:
DECLARE @j INT = 10;
SELECT DISTINCT TOP (@j) VAL
FROM X_10_DISTINCT_HEAP
OPTION (MAXDOP 1, OPTIMIZE FOR (@j = 1));
এই ক্যোয়ারী 2537 লজিক্যাল রিড করেছে। 2537 * 5 = 12685 যা প্রায় 12605 এর কাছাকাছি।
ক্লাস্টারড ইনডেক্স সহ টেবিলের জন্য আমরা আরও ভাল করতে পারি। এটি হ'ল কারণ একই সারিগুলিতে দু'বার স্ক্যান করা এড়াতে আমরা শেষ ক্লাস্টারযুক্ত মানটি উত্পন্ন টেবিলের মধ্যে দিয়ে যেতে পারি। একটি বাস্তবায়ন:
SELECT VAL
FROM (
SELECT t1.VAL VAL1, t2.VAL VAL2, t3.VAL VAL3, t4.VAL VAL4, t5.VAL VAL5, t6.VAL VAL6, t7.VAL VAL7, t8.VAL VAL8, t9.VAL VAL9, t10.VAL VAL10
FROM
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI
) t1
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t2 WHERE PK > t1.PK AND t2.VAL NOT IN (t1.VAL)
) t2
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t3 WHERE PK > t2.PK AND t3.VAL NOT IN (t1.VAL, t2.VAL)
) t3
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t4 WHERE PK > t3.PK AND t4.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL)
) t4
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t5 WHERE PK > t4.PK AND t5.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL)
) t5
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t6 WHERE PK > t5.PK AND t6.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL)
) t6
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t7 WHERE PK > t6.PK AND t7.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL)
) t7
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t8 WHERE PK > t7.PK AND t8.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL, t7.VAL)
) t8
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t9 WHERE PK > t8.PK AND t9.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL, t7.VAL, t8.VAL)
) t9
OUTER APPLY
(
SELECT TOP 1 PK, VAL FROM X_10_DISTINCT_CI t10 WHERE PK > t9.PK AND t10.VAL NOT IN (t1.VAL, t2.VAL, t3.VAL, t4.VAL, t5.VAL, t6.VAL, t7.VAL, t8.VAL, t9.VAL)
) t10
) t
UNPIVOT
(
VAL FOR VALS IN (VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL8, VAL9, VAL10)
) AS upvt;
উপরের ক্যোয়ারির জন্য প্রকৃত ক্যোয়ারী পরিকল্পনা এখানে । আমার মেশিনে এই কোয়েরিটি সিপিইউয়ের 140 এমএস এবং 3203 লজিক্যাল রিডের সাথে 154 এমএসে সম্পূর্ণ হয়। এটি OPTIMIZE FOR
ক্লাস্টারড ইনডেক্স টেবিলের বিপরীতে ক্যোয়ারির চেয়ে কিছুটা দ্রুত চলবে বলে মনে হয়েছিল । আমি আশা করছিলাম না তাই আমি আরও যত্ন সহকারে পরিমাপ করার চেষ্টা করেছি। আমার পদ্ধতি ফলাফলের সেট ছাড়া প্রতিটি প্রশ্নের সাথে দশ বার চালানোর থেকে সমষ্টিগত সংখ্যা তাকান ছিল sys.dm_exec_sessions
এবং sys.dm_exec_session_wait_stats
। সেশন 56 এর APPLY
ক্যোয়ারী ছিল এবং সেশন 63 এর OPTIMIZE FOR
ক্যোয়ারী ছিল ।
এর আউটপুট sys.dm_exec_sessions
:
╔════════════╦══════════╦════════════════════╦═══════════════╗
║ session_id ║ cpu_time ║ total_elapsed_time ║ logical_reads ║
╠════════════╬══════════╬════════════════════╬═══════════════╣
║ 56 ║ 1360 ║ 1373 ║ 32030 ║
║ 63 ║ 2094 ║ 2091 ║ 30400 ║
╚════════════╩══════════╩════════════════════╩═══════════════╝
ক্যোরির জন্য সিপু_টাইম এবং অতিবাহিত_টাইমের একটি সুস্পষ্ট সুবিধা বলে মনে হচ্ছে APPLY
।
এর আউটপুট sys.dm_exec_session_wait_stats
:
╔════════════╦════════════════════════════════╦═════════════════════╦══════════════╦══════════════════╦═════════════════════╗
║ session_id ║ wait_type ║ waiting_tasks_count ║ wait_time_ms ║ max_wait_time_ms ║ signal_wait_time_ms ║
╠════════════╬════════════════════════════════╬═════════════════════╬══════════════╬══════════════════╬═════════════════════╣
║ 56 ║ SOS_SCHEDULER_YIELD ║ 340 ║ 0 ║ 0 ║ 0 ║
║ 56 ║ MEMORY_ALLOCATION_EXT ║ 38 ║ 0 ║ 0 ║ 0 ║
║ 63 ║ SOS_SCHEDULER_YIELD ║ 518 ║ 0 ║ 0 ║ 0 ║
║ 63 ║ MEMORY_ALLOCATION_EXT ║ 98 ║ 0 ║ 0 ║ 0 ║
║ 63 ║ RESERVED_MEMORY_ALLOCATION_EXT ║ 400 ║ 0 ║ 0 ║ 0 ║
╚════════════╩════════════════════════════════╩═════════════════════╩══════════════╩══════════════════╩═════════════════════╝
OPTIMIZE FOR
ক্যোয়ারী একটি অতিরিক্ত অপেক্ষার টাইপ হয়েছে RESERVED_MEMORY_ALLOCATION_EXT । আমি এর সঠিক অর্থটি জানি না। এটি হ্যাশ ম্যাচ (প্রবাহ স্বতন্ত্র) অপারেটরে কেবল ওভারহেডের একটি পরিমাপ হতে পারে। যে কোনও ক্ষেত্রে, সম্ভবত এটি সিপিইউ সময়ে 70 এমএসের পার্থক্য সম্পর্কে উদ্বেগজনক নয়।