"ব্যয়" ধরে নেওয়া সময়ের শর্তে (যদিও এটি নিশ্চিত নয় যে এটি ;-) এর শর্তে আরও কী হতে পারে তবে খুব কমপক্ষে আপনাকে নিম্নলিখিতগুলির মতো কিছু করে বোঝার পক্ষে সক্ষম হতে হবে:
DBCC FREEPROCCACHE WITH NO_INFOMSGS;
SET STATISTICS TIME ON;
EXEC sp_help 'sys.databases'; -- replace with your proc
SET STATISTICS TIME OFF;
"বার্তা" ট্যাবে রিপোর্ট করা প্রথম আইটেমটি হ'ল:
এসকিউএল সার্ভার পার্স এবং সংকলন সময়:
আমি এটি কমপক্ষে 10 বার চালাব এবং গড় "সিপিইউ" এবং "বিচ্ছিন্ন" মিলিসেকেন্ড উভয়ই।
আদর্শভাবে আপনি এটি প্রোডাকশনে চালাতেন যাতে আপনি একটি সঠিক সময়ের অনুমান করতে পারেন তবে খুব কমই লোকেদের প্রোডাকশনের পরিকল্পনার ক্যাশে সাফ করার অনুমতি দেওয়া হয়। ভাগ্যক্রমে, এসকিউএল সার্ভার ২০০৮ সালে শুরু হয়ে ক্যাশে থেকে একটি নির্দিষ্ট পরিকল্পনা সাফ করা সম্ভব হয়েছিল। কোন ক্ষেত্রে আপনি নিম্নলিখিতটি করতে পারেন:
DECLARE @SQL NVARCHAR(MAX) = '';
;WITH cte AS
(
SELECT DISTINCT stat.plan_handle
FROM sys.dm_exec_query_stats stat
CROSS APPLY sys.dm_exec_text_query_plan(stat.plan_handle, 0, -1) qplan
WHERE qplan.query_plan LIKE N'%sp[_]help%' -- replace "sp[_]help" with proc name
)
SELECT @SQL += N'DBCC FREEPROCCACHE ('
+ CONVERT(NVARCHAR(130), cte.plan_handle, 1)
+ N');'
+ NCHAR(13) + NCHAR(10)
FROM cte;
PRINT @SQL;
EXEC (@SQL);
SET STATISTICS TIME ON;
EXEC sp_help 'sys.databases' -- replace with your proc
SET STATISTICS TIME OFF;
যাইহোক, "খারাপ" ক্যাশেড পরিকল্পনার কারণ হিসাবে প্যারামিটারগুলিতে পাস করা মানগুলির পরিবর্তনশীলতার উপর নির্ভর করে, ডায়নামিক এসকিউএল OPTION(RECOMPILE)
এবং এর মধ্যে একটি মাঝারি ক্ষেত্র বিবেচনা করার জন্য আরও একটি পদ্ধতি রয়েছে OPTION(OPTIMIZE FOR UNKNOWN)
। হ্যাঁ, আমি এটা বলেছি। এবং আমি এমনকি অ-পরামিতিযুক্ত ডায়নামিক এসকিউএল বোঝাতে চাইছি। এখানে কেন।
আপনার কাছে পরিষ্কারভাবে এমন ডেটা রয়েছে যা অন্তত এক বা একাধিক ইনপুট প্যারামিটার মানের ক্ষেত্রে অসম বন্টন করে। উল্লিখিত বিকল্পগুলির ডাউনসাইডগুলি হ'ল:
OPTION(RECOMPILE)
প্রতিটি মৃত্যুদন্ড কার্যকর করার জন্য একটি পরিকল্পনা তৈরি করে এবং আপনি কোনও প্ল্যান পুনরায় ব্যবহার থেকে কখনই উপকৃত হতে পারবেন না , এমনকি যদি আবার পাস হওয়া প্যারামিটার মানগুলি পূর্বের রান (গুলি) এর মতো হয়। প্রোকগুলির জন্য যা ঘন ঘন বলা হয় - প্রতি কয়েক সেকেন্ডে বা তার বেশি ঘন ঘন একবার - এটি আপনাকে মাঝে মাঝে ভয়ঙ্কর পরিস্থিতি থেকে রক্ষা করবে, তবে এখনও আপনাকে সর্বদা-সর্বশ্রেষ্ঠ নয় in
OPTION(OPTIMIZE FOR (@Param = value))
সেই নির্দিষ্ট মানের উপর ভিত্তি করে একটি পরিকল্পনা তৈরি করবে, যা বেশ কয়েকটি ক্ষেত্রে সহায়তা করতে পারে তবে তবুও আপনাকে বর্তমান ইস্যুতে খোলা রাখবে।
OPTION(OPTIMIZE FOR UNKNOWN)
গড় বিতরণের পরিমাণের ভিত্তিতে একটি পরিকল্পনা তৈরি করবে, যা কিছু প্রশ্নে সহায়তা করবে তবে অন্যকে আঘাত করবে। এটি স্থানীয় ভেরিয়েবলগুলি ব্যবহার করার বিকল্প হিসাবে একই হওয়া উচিত।
ডায়নামিক এসকিউএল, তবে, সঠিকভাবে সম্পন্ন করার পরে , বিভিন্ন মানগুলিকে পাস করার জন্য তাদের নিজস্ব পৃথক ক্যোয়ারী পরিকল্পনাগুলি আদর্শ যা ভাল হতে পারে (ভাল, যতটা তারা করবে তত পরিমাণে)। এখানে মূল ব্যয় হ'ল বিভিন্ন মান যত বাড়তে চলেছে, ক্যাশে কার্যকর করার পরিকল্পনার সংখ্যা বৃদ্ধি পায় এবং তারা স্মৃতি গ্রহণ করে। গৌণ ব্যয়গুলি হ'ল:
এসকিউএল ইনজেকশনগুলি রোধ করতে স্ট্রিং প্যারামিটারগুলি বৈধকরণ করা দরকার
ডায়নামিক এসকিউএল-এর সরাসরি টেবিল অনুমতি প্রয়োজন হওয়ায় সম্ভবত আদর্শ সুরক্ষা বিমূর্ততা বজায় রাখতে একটি শংসাপত্র এবং শংসাপত্র ভিত্তিক ব্যবহারকারী সেট আপ করা প্রয়োজন।
সুতরাং, আমি এখানে এই পরিস্থিতিটি কীভাবে পরিচালনা করেছি যখন আমার কাছে প্রতি সেকেন্ডে একাধিকবার ডাকা হত এবং একাধিক টেবিল হিট হয়েছিল, যার প্রত্যেকটিতে লক্ষ লক্ষ সারি রয়েছে। আমি চেষ্টা করেছিলাম OPTION(RECOMPILE)
কিন্তু 99% ক্ষেত্রে যে প্যারামিটার স্নিফিং / খারাপ ক্যাশেড প্ল্যান সমস্যা নেই তার ক্ষেত্রে এটি প্রক্রিয়াটির পক্ষে খুব ক্ষতিকারক প্রমাণিত। এবং দয়া করে মনে রাখবেন যে এগুলির একটিরও এর প্রায় 15 টি ক্যোয়ারী ছিল এবং তাদের মধ্যে কেবল 3 - 5 এখানে বর্ণিত হিসাবে ডায়নামিক এসকিউএল রূপান্তরিত হয়েছিল; গতিশীল এসকিউএল কোনও নির্দিষ্ট প্রশ্নের জন্য প্রয়োজনীয় না হলে ব্যবহৃত হত না।
যদি সঞ্চিত পদ্ধতিতে একাধিক ইনপুট প্যারামিটার থাকে, তবে কলামগুলির সাথে কোনটি ব্যবহৃত হয় যা উচ্চতর বিতরণকারী ডেটা বিতরণ করে (এবং ফলে এই সমস্যাটি ঘটায়) এবং কোনটি কলামগুলির সাথে আরও বেশি বিতরণ রয়েছে তা ব্যবহার করে (এবং এটি হওয়া উচিত নয়) এই সমস্যা সৃষ্টি করে)।
সমানভাবে বিতরণকৃত কলামগুলির সাথে সম্পর্কিত যেগুলি প্রোপ ইনপুট প্যারামিগুলির জন্য পরামিতিগুলি ব্যবহার করে ডায়নামিক এসকিউএল স্ট্রিং তৈরি করুন। এই প্যারামিটারাইজেশন এই প্রশ্নের সাথে সম্পর্কিত ক্যাশে কার্যকরকরণ পরিকল্পনার ফলস্বরূপ বৃদ্ধি হ্রাস করতে সহায়তা করে।
অবশিষ্ট পরামিতিগুলির জন্য যা উচ্চ বৈচিত্রপূর্ণ বিতরণের সাথে যুক্ত, তাদের আক্ষরিক মান হিসাবে ডায়নামিক এসকিউএল হিসাবে যুক্ত করা উচিত। যেহেতু একটি অনন্য ক্যোয়ারী ক্যোয়ারী পাঠ্যের যে কোনও পরিবর্তন দ্বারা নির্ধারিত হয়, WHERE StatusID = 1
হ'ল আলাদা ক্যোয়ারী হওয়া এবং তাই, আলাদা ক্যোয়ারী পরিকল্পনা থাকার চেয়ে WHERE StatusID = 2
।
কোয়েরির পাঠ্যের সাথে প্রনাক্ট ইনপুট প্যারামিটারগুলির মধ্যে যদি কোনও স্ট্রিং থাকে তবে এসকিউএল ইনজেকশন থেকে রক্ষা করার জন্য তাদের বৈধতা দেওয়া দরকার (যদিও স্ট্রিংগুলি পাস করা হচ্ছে যদি এটির সম্ভাবনা কম থাকে তবে অ্যাপ্লিকেশন এবং কোনও ব্যবহারকারী নয়, তবে এখনও)। কমপক্ষে REPLACE(@Param, '''', '''''')
সিঙ্গেল-কোটগুলি একক-কোট হয়ে যায় বলে নিশ্চিত হয়ে নিন।
যদি প্রয়োজন হয় তবে একটি শংসাপত্র তৈরি করুন যা ব্যবহারকারীর তৈরি করতে এবং সঞ্চিত পদ্ধতিতে স্বাক্ষর করার জন্য ব্যবহার করা হবে যেমন সরাসরি টেবিলের অনুমতি কেবল নতুন শংসাপত্র ভিত্তিক ব্যবহারকারীকে দেওয়া হবে এবং [public]
অন্যথায় এই জাতীয় অনুমতি না থাকা ব্যবহারকারীদের বা না ।
উদাহরণস্বরূপ:
CREATE PROCEDURE MySchema.MyProc
(
@Param1 INT,
@Param2 DATETIME,
@Param3 NVARCHAR(50)
)
AS
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'
SELECT tab.Field1, tab.Field2, ...
FROM MySchema.SomeTable tab
WHERE tab.Field3 = @P1
AND tab.Field8 >= CONVERT(DATETIME, ''' +
CONVERT(NVARCHAR(50), @Param2, 121) +
N''')
AND tab.Field2 LIKE N''' +
REPLACE(@Param3, N'''', N'''''') +
N'%'';';
EXEC sp_executesql
@SQL,
N'@P1 INT',
@P1 = @Param1;