এসকিউএল সার্ভার কোয়েরি অপ্টিমাইজার একক গণনা স্কেলার অপারেটরে পুনরাবৃত্তি গণনা করা মানগুলি একত্রিত করতে পারে। এটি করবে কি না তা নির্ভর করে ক্যোয়ারী পরিকল্পনার ব্যয় এবং গণিত মূল্যের বৈশিষ্ট্যের উপর। যেমনটি প্রত্যাশিত, এটি গণনা করা মানগুলির জন্য এটি করবে না যা ননডেটেরিস্টেমিক, যা কিছু ব্যতিক্রম যেমন RAND()। এটি ব্যবহারকারী সংজ্ঞায়িত ফাংশনগুলির জন্য এটি করবে না।
আমি একটি ব্যবহারকারী সংজ্ঞায়িত ফাংশন উদাহরণ দিয়ে শুরু করব। এখানে ব্যবহারকারীর সংজ্ঞায়িত ফাংশনটির একটি দুর্দান্ত উদাহরণ রয়েছে:
CREATE OR ALTER FUNCTION dbo.NULL_FUNCTION (@N BIGINT) RETURNS BIGINT
WITH SCHEMABINDING
AS
BEGIN
RETURN NULL;
END;
আমি একটি টেবিল তৈরি করতে এবং এটিতে 100 টি সারি রাখতে চাই:
CREATE TABLE X_100 (N BIGINT NOT NULL);
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)
INSERT INTO X_100 WITH (TABLOCK)
SELECT n
FROM Nums WHERE n <= 100;
dbo.NULL_FUNCTIONফাংশন determistic হয়। নিম্নলিখিত প্রশ্নের জন্য এটি কতবার কার্যকর করা হবে?
SELECT n, dbo.NULL_FUNCTION(n)
FROM X_100;
ক্যোয়ারী পরিকল্পনার ভিত্তিতে এটি প্রতিটি সারির জন্য একবার বা 100 বার কার্যকর করা হবে:

এসকিউএল সার্ভার 2016 sys.dm_exec_function_stats DMV প্রবর্তন করেছে । কোনও ডিভিউ কতবার ইউডিএফ দ্বারা কার্যকর করা হয় তা দেখতে আমরা সেই ডিএমভির স্ন্যাপশট নিতে পারি।
SELECT execution_count
FROM sys.dm_exec_function_stats
WHERE object_id = OBJECT_ID('NULL_FUNCTION');
এর ফলাফল 100, সুতরাং ফাংশনটি 100 বার কার্যকর করা হয়েছিল।
আসুন অন্য একটি সহজ ক্যোয়ারী চেষ্টা করুন:
SELECT n, dbo.NULL_FUNCTION(n), dbo.NULL_FUNCTION(n)
FROM X_100;
ক্যোয়ারী প্ল্যানটি পরামর্শ দেয় যে ফাংশনটি 200 বার কার্যকর করা হবে:

ফলাফলগুলি sys.dm_exec_function_statsসূচিত করে যে ফাংশনটি 200 বার কার্যকর করা হয়েছিল।
নোট করুন যে আপনি কোনও গণনা স্কেলার কতবার কার্যকর হয় তা নির্ধারণের জন্য আপনি সর্বদা ক্যোয়ারী পরিকল্পনাটি ব্যবহার করতে পারবেন না। নীচের উদ্ধৃতিটি " গণনা স্কেলারস, এক্সপ্রেশন এবং এক্সিকিউশন প্ল্যান পারফরম্যান্স " থেকে এসেছে:
এটি লোকেদের ভাবতে পরিচালিত করে যে কম্পিউট স্কেলার অন্যান্য অপারেটরের সংখ্যাগরিষ্ঠের মতো আচরণ করে: সারিগুলি এর মধ্য দিয়ে প্রবাহিত হওয়ায়, কম্পিউট স্কেলারের যে কোনও গণনাগুলির ফলাফল প্রবাহে যুক্ত হয়। এটি সাধারণত সত্য নয়। নাম সত্ত্বেও, কম্পিউট স্কেলার সর্বদা কোনও কিছুর গণনা করে না এবং সর্বদা একটি একক স্কেলারের মান ধারণ করে না (এটি উদাহরণস্বরূপ, একটি ভেক্টর, একটি এলিফ, এমনকি বুলিয়ান শিকারীও হতে পারে)। না প্রায়শই, একটি কম্পিউট স্কেলার কেবল একটি অভিব্যক্তি সংজ্ঞা দেয়; বাস্তবায়ন পরিকল্পনার পরে কোনও ফলাফলের প্রয়োজন না হওয়া পর্যন্ত আসল গণনা পিছিয়ে যায়।
আরেকটি উদাহরণ চেষ্টা করুন। নিম্নলিখিত প্রশ্নের জন্য আমি আশা করব যে ইউডিএফ একবারে গণনা করা হয়েছে:
WITH NULL_FUNCTION_CTE (NULL_VALUE) AS
(
SELECT DISTINCT dbo.NULL_FUNCTION(0)
)
SELECT n , cte.NULL_VALUE
FROM X_100
CROSS JOIN NULL_FUNCTION_CTE cte;
ক্যোয়ারী প্ল্যান পরামর্শ দেয় যে এটি একবারে গণনা করা হবে:

তবে, ডিএমভি সত্য প্রকাশ করে। এটি প্রয়োজন না হওয়া পর্যন্ত গণনা স্কেলারটি পিছিয়ে দেওয়া হয় যা জোড় অপারেটরে থাকে। এটি 100 বার মূল্যায়ন করা হয়।
আপনি একই প্রশ্নটি একাধিকবার পুনরায় গণনা এড়াতে অপ্টিমাইজারকে উত্সাহিত করতে আপনি কী করতে পারেন তাও জিজ্ঞাসা করেছিলেন। আপনার কোডটিতে স্কেলারার ইউডিএফ ব্যবহার করা এড়ানো সেরা কাজটি আপনি করতে পারেন। এগুলির মেমরি অনুদানের স্ফীতকরণ, পুরো ক্যোয়ারীটি চালাতে বাধ্য করা MAXDOP 1, খারাপ কার্ডিনালিটির অনুমান, এবং অতিরিক্ত সিপিইউ ব্যবহারের দিকে পরিচালিত করা সহ এই প্রশ্নের বাইরে অনেকগুলি কার্য সম্পাদনের সমস্যা রয়েছে । আপনার যদি কোনও ইউডিএফ ব্যবহার করার প্রয়োজন হয় এবং সেই ইউডিএফটির মান একটি ধ্রুবক হয় তবে আপনি এটিকে ক্যোয়ারির বাইরে গণনা করতে এবং স্থানীয় ভেরিয়েবলে রাখতে পারেন।
ইউডিএফবিহীন প্রশ্নের জন্য, আপনি বাক্যগুলি এড়াতে চেষ্টা করতে পারেন যা একই ফলাফলটি ফিরে আসে তবে ঠিক একইভাবে টাইপ করা হয় না। এই পরবর্তী উদাহরণের জন্য আমি সর্বজনীনভাবে উপলভ্য অ্যাডভেঞ্চারওয়ার্সডডাব্লু2016সিটিপি 3 ডাটাবেসটি ব্যবহার করছি, তবে সত্যিই কোনও ডাটাবেসই করবে। COUNT(*)এই ক্যোয়ারির জন্য কতবার গণনা করা হবে ?
SELECT OrderDateKey, COUNT(*)
FROM dbo.FactResellerSales
GROUP BY OrderDateKey
ORDER BY COUNT(*) DESC;
এই প্রশ্নের জন্য আমরা হ্যাশ ম্যাচ (সমষ্টিগত) অপারেটরটি দেখে এটি বের করতে পারি।

এর COUNT(*)প্রতিটি অনন্য মানের জন্য একবার গণনা করা হয় OrderDateKey। ক্লজটি অন্তর্ভুক্ত করার ORDER BYকারণে এটি দুটিবার গণনা করতে পারে না। আপনি এখানে কার্যকর করতে পারেন পরিকল্পনা ।
এখন, এমন একটি ক্যোয়ারী বিবেচনা করুন যা ঠিক একই ফলাফল প্রদান করবে তবে ভিন্নভাবে লেখা হয়েছে:
SELECT OrderDateKey, SUM(1)
FROM dbo.FactResellerSales
GROUP BY OrderDateKey
ORDER BY COUNT(*) DESC;
কোয়েরি অপ্টিমাইজার তাদের একত্রিত করার জন্য যথেষ্ট স্মার্ট নয়, তাই অতিরিক্ত কাজ করা হবে:
