শেষ পর্যন্ত, এসকিউএল সার্ভারকে কোনও ক্যোয়ারীতে একবারই কোনও স্কেলারের ইউডিএফ মূল্যায়ন করতে বাধ্য করা সম্ভব নয়। তবে কিছু পদক্ষেপ রয়েছে যা এটিকে উত্সাহ দেওয়ার জন্য নেওয়া যেতে পারে। পরীক্ষার মাধ্যমে আমি বিশ্বাস করি যে আপনি এসকিউএল সার্ভারের বর্তমান সংস্করণটির সাথে কাজ করে এমন কিছু পেতে পারেন তবে ভবিষ্যতে পরিবর্তনগুলির জন্য আপনার কোডটি পুনরায় দেখা দরকার।
যদি কোডটি সম্পাদনা করা সম্ভব হয় তবে প্রথমে চেষ্টা করার চেষ্টা করা সম্ভব হ'ল যদি সম্ভব হয় তবে ফাংশনটিকে নির্বিচারে তৈরি করা। পল হোয়াইট এখানে উল্লেখ করেছেন যে ফাংশনটি অবশ্যই SCHEMABINDING
বিকল্পের সাথে তৈরি করা উচিত এবং ফাংশন কোডটি অবশ্যই ডিটারিমেন্টিক হতে হবে।
নিম্নলিখিত পরিবর্তন করার পরে:
CREATE OR ALTER FUNCTION dbo.EXPENSIVE_UDF () RETURNS INT
WITH SCHEMABINDING
AS
BEGIN
DECLARE @tbl TABLE (VAL VARCHAR(5));
-- make the function expensive to call
INSERT INTO @tbl
SELECT [VALUE]
FROM STRING_SPLIT(REPLICATE(CAST('Z ' AS VARCHAR(MAX)), 20000), ' ');
RETURN 1;
END;
প্রশ্ন থেকে ক্যোয়ারী 64৪ এমএসে কার্যকর করা হয়েছে:
SELECT x1.ID
FROM dbo.X_100_INTEGERS x1
WHERE x1.ID >= dbo.EXPENSIVE_UDF();
ক্যোয়ারী প্ল্যানটির আর ফিল্টার অপারেটর নেই:
এটি নিশ্চিত হওয়ার জন্য যে এটি কেবলমাত্র একবার কার্যকর হয়েছিল যখন আমরা এসকিউএল সার্ভার 2016 এ প্রকাশিত নতুন sys.dm_exec_function_stats DMV ব্যবহার করতে পারি :
SELECT execution_count
FROM sys.dm_exec_function_stats
WHERE object_id = OBJECT_ID('EXPENSIVE_UDF', 'FN');
ALTER
ফাংশনটির বিরুদ্ধে একটি ইস্যু করা execution_count
সেই বস্তুর জন্য পুনরায় সেট করবে । উপরের ক্যোয়ারী 1 প্রদান করে যার অর্থ ফাংশনটি কেবল একবার কার্যকর করা হয়েছিল।
মনে রাখবেন যে কেবলমাত্র ফাংশনটি ডিটারমিনিস্টিক এর অর্থ এই নয় যে কোনও প্রশ্নের জন্য এটি একবারে মূল্যায়ন করা হবে। আসলে, কিছু প্রশ্নের জন্য যুক্ত করা SCHEMABINDING
কর্মক্ষমতা হ্রাস করতে পারে। নিম্নলিখিত কোয়েরি বিবেচনা করুন:
WITH cte (UDF_VALUE) AS
(
SELECT DISTINCT dbo.EXPENSIVE_UDF() UDF_VALUE
)
SELECT ID
FROM dbo.X_100_INTEGERS
INNER JOIN cte ON ID >= cte.UDF_VALUE;
DISTINCT
ফিল্টার অপারেটর থেকে মুক্তি পেতে অতিরিক্ত অতিরিক্ত যুক্ত করা হয়েছিল। পরিকল্পনাটি আশাব্যঞ্জক বলে মনে হচ্ছে:
তার উপর ভিত্তি করে, কেউ প্রত্যাশা করবে যে ইউডিএফ একবার মূল্যায়ন হবে এবং নেস্টেড লুপ জোনে বাইরের টেবিল হিসাবে ব্যবহৃত হবে। যাইহোক, ক্যোয়ারীটি আমার মেশিনে চালাতে 6446 এমএস লাগে। sys.dm_exec_function_stats
ফাংশন অনুযায়ী 100 বার কার্যকর করা হয়েছিল। কীভাবে সম্ভব? " কম্পিউট স্কেলারস, এক্সপ্রেশন এবং এক্সিকিউশন প্ল্যান পারফরম্যান্স " এ, পল হোয়াইট উল্লেখ করেছেন যে কম্পিউট স্কেলার অপারেটর পিছিয়ে দেওয়া যেতে পারে:
না প্রায়শই, একটি কম্পিউট স্কেলার কেবল একটি অভিব্যক্তি সংজ্ঞা দেয়; বাস্তবায়ন পরিকল্পনার পরে কোনও ফলাফলের প্রয়োজন না হওয়া পর্যন্ত আসল গণনা পিছিয়ে যায়।
এই ক্যোয়ারির জন্য দেখে মনে হচ্ছে ইউডিএফ কলটি প্রয়োজনীয় না হওয়া পর্যন্ত পিছিয়ে গেছে, যার সময়ে এটি 100 বার মূল্যায়ন করা হয়েছিল।
মজার বিষয় হল, সিডিই উদাহরণটি যখন আমার SCHEMABINDING
প্রশ্নের সাথে ইউডিএফ সংজ্ঞায়িত না করা হয় তখন আমার মেশিনে 71 এমএসে কার্যকর করে । কোয়েরিটি চালিত হলে ফাংশনটি একবার কার্যকর করা হয়। এখানে তার জন্য ক্যোয়ারী পরিকল্পনাটি দেওয়া হল:
এটি স্পষ্ট নয় যে কেন কম্পিউট স্কেলার পিছিয়ে নেই। এটি হতে পারে কারণ ক্রিয়াকলাপের অ-নির্ধারিততা ক্যোয়ারী অপ্টিমাইজারটি করতে পারে এমন অপারেটরদের পুনর্বিন্যাসকে সীমাবদ্ধ করে।
বিকল্প বিকল্প হল সিটিইতে একটি ছোট টেবিল যুক্ত করা এবং সেই টেবিলের একমাত্র সারিটি জিজ্ঞাসা করা। যে কোনও ছোট টেবিলটি করবে, তবে আসুন নিম্নলিখিতটি ব্যবহার করুন:
CREATE TABLE dbo.X_ONE_ROW_TABLE (ID INT NOT NULL);
INSERT INTO dbo.X_ONE_ROW_TABLE VALUES (1);
কোয়েরিটি তখন পরিণত হয়:
WITH cte (UDF_VALUE) AS
(
SELECT DISTINCT dbo.EXPENSIVE_UDF() UDF_VALUE
FROM dbo.X_ONE_ROW_TABLE
)
SELECT ID
FROM dbo.X_100_INTEGERS
INNER JOIN cte ON ID >= cte.UDF_VALUE;
সংযোজনগুলির সংযোজন dbo.X_ONE_ROW_TABLE
অপ্টিমাইজারের জন্য অনিশ্চয়তা যুক্ত করে। যদি টেবিলটিতে শূন্য সারি থাকে তবে সিটিই 0 টি সারি ফিরে আসবে। যে কোনও ক্ষেত্রে, অপ্টিমাইজার গ্যারান্টি দিতে পারে না যে ইউডিএফ যদি সংজ্ঞাবাদী না হয় তবে সিটিই এক সারিতে ফিরে আসবে, তাই সম্ভবত যুক্ত হওয়ার আগে ইউডিএফকে মূল্যায়ন করা হবে বলে মনে হয়। আমি প্রত্যাশা করব যে অপটিমাইজারটি স্ক্যান করবে dbo.X_ONE_ROW_TABLE
, এক সারিটির সর্বাধিক মান ফিরে আসার জন্য একটি স্ট্রিম সমষ্টি ব্যবহার করবে (যার জন্য ফাংশনটি মূল্যায়ন করা দরকার), এবং এটি একটি নেস্টেড লুপের জন্য বাইরের টেবিল হিসাবে dbo.X_100_INTEGERS
মূল ক্যোয়ারিতে যোগ দিতে হবে । এই উপস্থিত হতে পারে সেখানে কি ঘটছে :
ক্যোরিটি আমার মেশিনে প্রায় 110 এমএসে কার্যকর করে এবং ইউডিএফ কেবলমাত্র একবার অনুযায়ী মূল্যায়ন করা হয় sys.dm_exec_function_stats
। এটি বলা ভুল হবে যে ক্যোয়ারী অপ্টিমাইজার কেবল একবারই ইউডিএফ মূল্যায়ন করতে বাধ্য হয়। তবে, ইউডিএফ এবং কম্পিউট স্কেলারের ব্যয়ের সীমাবদ্ধতা থাকা সত্ত্বেও, এমন একটি অপ্টিমাইজার পুনরায় লেখার কল্পনা করা শক্ত যা কম দামের ক্যোয়ারী তৈরি করে।
সংক্ষেপে, নির্বাহী ফাংশনগুলির জন্য (যা অবশ্যই SCHEMABINDING
বিকল্পটি অন্তর্ভুক্ত করতে পারে ) কোয়েরিটি যথাসম্ভব সহজভাবে লেখার চেষ্টা করুন। যদি এসকিউএল সার্ভার 2016 বা পরবর্তী সংস্করণে থাকে তবে নিশ্চিত হয়ে নিন যে ফাংশনটি একবার ব্যবহার করার পরে কার্যকর হয়েছিল sys.dm_exec_function_stats
। কার্যকর করার পরিকল্পনাগুলি সে ক্ষেত্রে বিভ্রান্তিকর হতে পারে।
এসকিউএল সার্ভার কর্তৃক অপ্রয়োজনীয় কিছু সহ ডিটারিস্টিনিস্টিক হিসাবে বিবেচিত নয় এমন ক্রিয়াকলাপগুলির জন্য SCHEMABINDING
, একটি পদ্ধতির হ'ল ইউডিএফটিকে সাবধানতার সাথে তৈরি সিটিই বা উত্পন্ন টেবিলের মধ্যে রাখা। এর জন্য একটু যত্ন নেওয়া প্রয়োজন তবে একই সিটিই ডিটারমিনিস্টিক এবং ননডেটারিস্টেমনিক উভয় ফাংশনের জন্যই কাজ করতে পারে।