এটি সাধারণভাবে সমাধান করা একটি কঠিন সমস্যা, তবে অপটিমাইজার একটি পরিকল্পনা বেছে নিতে সহায়তা করতে আমরা কয়েকটি জিনিস করতে পারি। এই স্ক্রিপ্টটি 10,000 টি সারি দিয়ে একটি সারণী তৈরি করে যা সুনির্দিষ্ট ছদ্ম-এলোমেলো বন্টন সারণীর বর্ণনা সহ:
CREATE TABLE dbo.SomeDateTable
(
Id INTEGER IDENTITY(1, 1) PRIMARY KEY NOT NULL,
StartDate DATETIME NOT NULL,
EndDate DATETIME NOT NULL
);
GO
SET STATISTICS XML OFF
SET NOCOUNT ON;
DECLARE
@i INTEGER = 1,
@s FLOAT = RAND(20120104),
@e FLOAT = RAND();
WHILE @i <= 10000
BEGIN
INSERT dbo.SomeDateTable
(
StartDate,
EndDate
)
VALUES
(
DATEADD(DAY, @s * 365, {d '2009-01-01'}),
DATEADD(DAY, @s * 365 + @e * 14, {d '2009-01-01'})
)
SELECT
@s = RAND(),
@e = RAND(),
@i += 1
END
প্রথম প্রশ্নটি হল এই টেবিলটি কীভাবে সূচক করা যায়। একটি বিকল্প দুটি ইনডেক্স প্রদান করা হয় DATETIME
, কলাম তাই অপটিমাইজার অন্তত উপর চাইতে হবে কিনা তা নির্বাচন করতে পারবেন StartDate
বা EndDate
।
CREATE INDEX nc1 ON dbo.SomeDateTable (StartDate, EndDate)
CREATE INDEX nc2 ON dbo.SomeDateTable (EndDate, StartDate)
স্বাভাবিকভাবেই, উভয় ক্ষেত্রেই অসমতা StartDate
এবং এর EndDate
অর্থ হ'ল প্রতিটি সূচকের কেবল একটি কলাম উদাহরণ ক্যোয়ারির অন্বেষণকে সমর্থন করতে পারে, তবে এটি আমাদের পক্ষে সবচেয়ে ভাল। আমরা প্রতিটি সূচকে দ্বিতীয় কলামটি INCLUDE
কী-এর পরিবর্তে তৈরি করার বিষয়টি বিবেচনা করতে পারি, তবে আমাদের অন্যান্য প্রশ্ন থাকতে পারে যা নেতৃস্থানীয় কলামে সাম্যতা এবং দ্বিতীয় কলামে অসমতার সন্ধান করতে পারে। এছাড়াও, আমরা এইভাবে আরও ভাল পরিসংখ্যান পেতে পারি। যাই হোক ...
DECLARE
@StartDateBegin DATETIME = {d '2009-08-01'},
@StartDateEnd DATETIME = {d '2009-10-15'},
@EndDateBegin DATETIME = {d '2009-08-05'},
@EndDateEnd DATETIME = {d '2009-10-22'}
SELECT
COUNT_BIG(*)
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.StartDate BETWEEN @StartDateBegin AND @StartDateEnd
AND sdt.EndDate BETWEEN @EndDateBegin AND @EndDateEnd
এই ক্যোয়ারীটি ভেরিয়েবলগুলি ব্যবহার করে, তাই সাধারণভাবে অপটিমাইজারটি নির্বাচন এবং বিতরণে অনুমান করবে, ফলস্বরূপ 81 টি সারির অনুমানযুক্ত কার্ডিনালিটির অনুমান । আসলে, ক্যোয়ারী 2076 টি সারি তৈরি করে, একটি তাত্পর্য যা আরও জটিল উদাহরণে গুরুত্বপূর্ণ হতে পারে।
এসকিউএল সার্ভার 2008 এসপি 1 CU5 বা পরে (অথবা R2 হলো RTM CU1) আমরা সুবিধা গ্রহণ করতে পারেন প্যারামিটার এমবেডিং অপ্টিমাইজেশান ভাল অনুমান করতে, খালি যোগ করে OPTION (RECOMPILE)
করতে SELECT
উপরে জিজ্ঞাস্য। এটি ব্যাচ কার্যকর হওয়ার ঠিক আগে সংকলন সৃষ্টি করে, এসকিউএল সার্ভারকে আসল প্যারামিটারের মানগুলি 'দেখতে' দেয় এবং সেগুলির জন্য অনুকূলিত করে। এই পরিবর্তনের সাথে সাথে অনুমানটি 468 টি সারিতে উন্নত হয় (যদিও এটি দেখার জন্য আপনাকে রানটাইম পরিকল্পনাটি পরীক্ষা করা দরকার)। এই অনুমানটি 81 টি সারির চেয়ে ভাল তবে এখনও এটি খুব কাছে নয়। ট্রেস পতাকা 2301 দ্বারা সক্ষম হওয়া মডেলিং এক্সটেনশানগুলি কিছু ক্ষেত্রে সহায়তা করতে পারে তবে এই ক্যোয়ারির সাথে নয়।
সমস্যাটি হ'ল দুটি সীমা অনুসন্ধানগুলি ওভারল্যাপের দ্বারা সারিগুলি যোগ্য করে তুলেছে। অপ্টিমাইজারের ব্যয় এবং কার্ডিনালিটি অনুমানের উপাদানটিতে করা সরলকরণ অনুমানগুলির মধ্যে একটি হ'ল পূর্বাভাসগুলি স্বতন্ত্র (তাই উভয়ই যদি 50% এর বেছে বেছে থাকে তবে উভয় প্রয়োগের ফলাফলটি 50% = 25% সারিতে 50% যোগ্য বলে ধরে নেওয়া হয়) )। এই ধরণের পারস্পরিক সম্পর্কের ক্ষেত্রে আমরা এখানে প্রায়শই বহু-কলাম এবং / অথবা ফিল্টার করা পরিসংখ্যান নিয়ে কাজ করতে পারি। অজানা শুরু এবং শেষ পয়েন্ট সহ দুটি ব্যাপ্তি সহ, এটি অযৌক্তিক হয়ে ওঠে। এখান থেকে আমাদের মাঝে মাঝে ক্যোয়ারিকে এমন ফর্মটিতে পুনরায় লেখার অবলম্বন করতে হয় যা আরও ভাল অনুমানের উত্পাদন ঘটে:
SELECT COUNT(*) FROM
(
SELECT
sdt.Id
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.StartDate BETWEEN @StartDateBegin AND @StartDateEnd
INTERSECT
SELECT
sdt.Id
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.EndDate BETWEEN @EndDateBegin AND @EndDateEnd
) AS intersected (id)
OPTION (RECOMPILE)
এই ফর্মটি 2110 সারিগুলির একটি রানটাইমের প্রাক্কলন ঘটায় (2076 আসল বিপরীতে)। আপনার যদি টিএফ 2301 না থাকে তবে সেক্ষেত্রে আরও উন্নত মডেলিং কৌশলগুলি কৌশলটি দেখে এবং ঠিক আগের মতোই প্রাক্কলন উত্পাদন করে: 468 সারি।
একদিন এসকিউএল সার্ভার অন্তরগুলির জন্য স্থানীয় সমর্থন অর্জন করতে পারে। যদি এটির পরিসংখ্যানগত সমর্থনটি আসে তবে বিকাশকারীরা এই জাতীয় ক্যোয়ারী পরিকল্পনাগুলিকে কিছুটা কমই ভয় করতে পারে।