উত্তর বিভাগ
বিভিন্ন টি-এসকিউএল কনস্ট্রাক্টস ব্যবহার করে এটি পুনরায় লেখার বিভিন্ন উপায় রয়েছে। আমরা উপকারিতা এবং নীতিগুলি দেখুন এবং নীচে একটি সামগ্রিক তুলনা করব।
প্রথম আপ : ব্যবহারOR
SELECT COUNT(*)
FROM dbo.Users AS u
WHERE u.Age < 18
OR u.Age IS NULL;
ব্যবহারের ফলে OR
আমাদের আরও কার্যকর সিক প্ল্যান দেয়, যা আমাদের প্রয়োজনীয় সারিগুলির সঠিক সংখ্যাটি পড়ে, তবে এটি প্রযুক্তি সম্পর্কিত বিশ্বকে a whole mess of malarkey
কোয়েরি পরিকল্পনায় ডাকে ।
এছাড়াও লক্ষ করুন যে সিক এখানে দু'বার মৃত্যুদন্ড কার্যকর করা হয়েছে যা গ্রাফিকাল অপারেটর থেকে সত্যই আরও স্পষ্ট হওয়া উচিত:
Table 'Users'. Scan count 2, logical reads 8233, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 469 ms, elapsed time = 473 ms.
সেকেন্ড আপ : UNION ALL
আমাদের ক্যোয়ারীর সাহায্যে উত্সযুক্ত টেবিলগুলি ব্যবহার করেও এটি আবার লিখিত যেতে পারে
SELECT SUM(Records)
FROM
(
SELECT COUNT(Id)
FROM dbo.Users AS u
WHERE u.Age < 18
UNION ALL
SELECT COUNT(Id)
FROM dbo.Users AS u
WHERE u.Age IS NULL
) x (Records);
এটি একই ধরণের পরিকল্পনার ফলস্বরূপ, কম কম ম্যালার্কি সহ এবং সূচকটি কতবার চাওয়া হয়েছে (চাওয়া?) তার সম্পর্কে আরও স্পষ্টতই সততা অর্জন করা।
এটি OR
ক্যোয়ারির সমান পরিমাণ পাঠ (8233) করে তবে প্রায় 100 মিমি সিপিইউ সময় বন্ধ করে দেয়।
CPU time = 313 ms, elapsed time = 315 ms.
তবে আপনাকে এখানে সত্যিই সতর্ক হতে হবে , কারণ এই পরিকল্পনাটি যদি সমান্তরাল হওয়ার চেষ্টা করে তবে দুটি পৃথক COUNT
ক্রিয়াকলাপ সিরিয়ালায়িত হবে, কারণ তারা প্রত্যেকে বিশ্বব্যাপী স্কেলার সমষ্টি হিসাবে বিবেচিত হয়। আমরা যদি ট্রেস ফ্ল্যাগ 8649 ব্যবহার করে একটি সমান্তরাল পরিকল্পনা জোর করি তবে সমস্যাটি সুস্পষ্ট হয়ে যায়।
SELECT SUM(Records)
FROM
(
SELECT COUNT(Id)
FROM dbo.Users AS u
WHERE u.Age < 18
UNION ALL
SELECT COUNT(Id)
FROM dbo.Users AS u
WHERE u.Age IS NULL
) x (Records)
OPTION(QUERYTRACEON 8649);
আমাদের ক্যোয়ারিটি কিছুটা পরিবর্তন করে এড়ানো যায়।
SELECT SUM(Records)
FROM
(
SELECT 1
FROM dbo.Users AS u
WHERE u.Age < 18
UNION ALL
SELECT 1
FROM dbo.Users AS u
WHERE u.Age IS NULL
) x (Records)
OPTION(QUERYTRACEON 8649);
এখন সিকের জন্য সম্পাদনা করা উভয় নোড পুরোপুরি সমান্তরাল হয় যতক্ষণ না আমরা কনকেশনেশন অপারেটরটিকে আঘাত করি।
এটি মূল্যবান কিসের জন্য, সম্পূর্ণ সমান্তরাল সংস্করণটির কিছু ভাল সুবিধা রয়েছে। আরও প্রায় 100 টি পঠন এবং 90 মিলিয়ন অতিরিক্ত সিপিইউয়ের সময় ব্যয় করা সময়টি 93 এমএসে সঙ্কুচিত হয়।
Table 'Users'. Scan count 12, logical reads 8317, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 500 ms, elapsed time = 93 ms.
ক্রস আবেদন সম্পর্কে কি?
এর জাদু ছাড়া কোনও উত্তরই সম্পূর্ণ নয় CROSS APPLY
!
দুর্ভাগ্যক্রমে, আমরা আরও সমস্যায় পড়েছি COUNT
।
SELECT SUM(Records)
FROM dbo.Users AS u
CROSS APPLY
(
SELECT COUNT(Id)
FROM dbo.Users AS u2
WHERE u2.Id = u.Id
AND u2.Age < 18
UNION ALL
SELECT COUNT(Id)
FROM dbo.Users AS u2
WHERE u2.Id = u.Id
AND u2.Age IS NULL
) x (Records);
এই পরিকল্পনাটি ভয়াবহ। আপনি যখন সেন্ট প্যাট্রিক্স ডে শেষ দেখবেন তখন এই জাতীয় পরিকল্পনার সমাপ্তি ঘটে। সুন্দরভাবে সমান্তরাল হলেও কিছু কারণে এটি পিকে / সিএক্স স্ক্যান করছে। ইডব্ল্যু। এই পরিকল্পনার 2198 টি ক্যোয়ারী টাকা রয়েছে has
Table 'Users'. Scan count 7, logical reads 31676233, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 29532 ms, elapsed time = 5828 ms.
যা একটি অদ্ভুত পছন্দ, কারণ যদি আমরা এটি অবিবাহিত সূচকটি ব্যবহার করতে বাধ্য করি তবে ব্যয়টি উল্লেখযোগ্যভাবে 1798 কোয়েরি বাক্সে নেমে আসে।
SELECT SUM(Records)
FROM dbo.Users AS u
CROSS APPLY
(
SELECT COUNT(Id)
FROM dbo.Users AS u2 WITH (INDEX(ix_Id_Age))
WHERE u2.Id = u.Id
AND u2.Age < 18
UNION ALL
SELECT COUNT(Id)
FROM dbo.Users AS u2 WITH (INDEX(ix_Id_Age))
WHERE u2.Id = u.Id
AND u2.Age IS NULL
) x (Records);
আরে, সন্ধান! আপনি সেখানে পরীক্ষা করে দেখুন। এছাড়াও লক্ষ করুন যে এর CROSS APPLY
যাদুটির সাথে, বেশিরভাগ সম্পূর্ণ সমান্তরাল পরিকল্পনা করার জন্য আমাদের বোকা কিছু করার দরকার নেই।
Table 'Users'. Scan count 5277838, logical reads 31685303, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 27625 ms, elapsed time = 4909 ms.
ক্রস অ্যাপ্লিকেশন COUNT
সেখানে স্টাফ ছাড়াই ফোরিং ভাল শেষ হয়।
SELECT SUM(Records)
FROM dbo.Users AS u
CROSS APPLY
(
SELECT 1
FROM dbo.Users AS u2
WHERE u2.Id = u.Id
AND u2.Age < 18
UNION ALL
SELECT 1
FROM dbo.Users AS u2
WHERE u2.Id = u.Id
AND u2.Age IS NULL
) x (Records);
পরিকল্পনাটি দেখতে দুর্দান্ত, তবে পঠন এবং সিপিইউ কোনও উন্নতি নয়।
Table 'Users'. Scan count 20, logical reads 17564, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 4844 ms, elapsed time = 863 ms.
ক্রসটি পুনরায় লেখালেখি হ'ল উদ্ভূত যুক্ত হওয়ার জন্য প্রয়োগ করা হয় ঠিক একই জিনিসটিতে। আমি ক্যোয়ারী পরিকল্পনা এবং পরিসংখ্যান তথ্য পুনরায় পোস্ট করতে যাচ্ছি না - সেগুলি সত্যিই পরিবর্তন হয়নি।
SELECT COUNT(u.Id)
FROM dbo.Users AS u
JOIN
(
SELECT u.Id
FROM dbo.Users AS u
WHERE u.Age < 18
UNION ALL
SELECT u.Id
FROM dbo.Users AS u
WHERE u.Age IS NULL
) x ON x.Id = u.Id;
রিলেশনাল বীজগণিত : পুরোপুরি হয়ে উঠতে এবং জো সেলকোকে আমার স্বপ্নগুলি ঘৃণা থেকে বিরত রাখতে আমাদের কমপক্ষে কিছু অদ্ভুত সম্পর্কযুক্ত জিনিস চেষ্টা করা দরকার। এখানেও যায় না '!
সঙ্গে একটি প্রচেষ্টা INTERSECT
SELECT COUNT(*)
FROM dbo.Users AS u
WHERE NOT EXISTS ( SELECT u.Age WHERE u.Age >= 18
INTERSECT
SELECT u.Age WHERE u.Age IS NOT NULL );
Table 'Users'. Scan count 1, logical reads 9157, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1094 ms, elapsed time = 1090 ms.
এবং এখানে একটি প্রচেষ্টা আছে EXCEPT
SELECT COUNT(*)
FROM dbo.Users AS u
WHERE NOT EXISTS ( SELECT u.Age WHERE u.Age >= 18
EXCEPT
SELECT u.Age WHERE u.Age IS NULL);
Table 'Users'. Scan count 7, logical reads 9247, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 2126 ms, elapsed time = 376 ms.
এগুলি লেখার অন্যান্য উপায়ও থাকতে পারে তবে আমি এগুলি এমন লোকদের মধ্যে রেখে দেব যারা সম্ভবত আমার চেয়ে বেশি ব্যবহার করে EXCEPT
এবং INTERSECT
প্রায়শই ব্যবহার করে ।
আপনার যদি সত্যিইCOUNT
আমার শঙ্কার কিছুটা হিসাবে আমার প্রশ্নগুলিতে
ব্যবহার করার মতো একটি গণনা প্রয়োজন (পড়ুন: আমি কখনও কখনও আরও জড়িত পরিস্থিতিগুলির সাথে আসতে পারি না)। আপনার যদি কেবল একটি গণনা প্রয়োজন, আপনি CASE
একই জিনিসটি করতে কেবল একটি এক্সপ্রেশন ব্যবহার করতে পারেন ।
SELECT SUM(CASE WHEN u.Age < 18 THEN 1
WHEN u.Age IS NULL THEN 1
ELSE 0 END)
FROM dbo.Users AS u
SELECT SUM(CASE WHEN u.Age < 18 OR u.Age IS NULL THEN 1
ELSE 0 END)
FROM dbo.Users AS u
এই উভয় একই পরিকল্পনা পান এবং একই সিপিইউ রয়েছে এবং পড়ার বৈশিষ্ট্য রয়েছে।
Table 'Users'. Scan count 1, logical reads 9157, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 719 ms, elapsed time = 719 ms.
বিজয়ী?
আমার পরীক্ষাগুলিতে, উত্পন্ন টেবিলের উপর এসইউমের সাথে বাধ্যতামূলক সমান্তরাল পরিকল্পনাটি সর্বোত্তমভাবে সম্পাদন করেছিল। এবং হ্যাঁ, উভয় পূর্বাভাসের জন্য অ্যাকাউন্টে দু'টি ফিল্টার সূচক যুক্ত করে এই প্রশ্নের অনেকগুলিই সহায়তা করা যেতে পারে, তবে আমি কিছু পরীক্ষা অন্যের কাছে রেখে যেতে চেয়েছিলাম।
SELECT SUM(Records)
FROM
(
SELECT 1
FROM dbo.Users AS u
WHERE u.Age < 18
UNION ALL
SELECT 1
FROM dbo.Users AS u
WHERE u.Age IS NULL
) x (Records)
OPTION(QUERYTRACEON 8649);
ধন্যবাদ!
NOT EXISTS ( INTERSECT / EXCEPT )
প্রশ্নের ছাড়া কাজ করবোINTERSECT / EXCEPT
অংশ:WHERE NOT EXISTS ( SELECT u.Age WHERE u.Age >= 18 );
আরেকটি উপায় - ব্যবহার করেEXCEPT
:SELECT COUNT(*) FROM (SELECT UserID FROM dbo.Users EXCEPT SELECT UserID FROM dbo.Users WHERE u.Age >= 18) AS u ;
(যেখানে আইডি পি কে বা কোন অনন্য নয় নাল কলাম (গুলি) যায়)।