دستور OPTION (RECOMPILE, OPTIMIZE FOR UNKNOWN) در SQL Server یکی از گزینههای Query Hint است که رفتار Optimizer رو روی اجرای یک کوئری خاص کنترل میکنه. بذار مرحلهبهمرحله توضیح بدم:
1. RECOMPILE
این بخش باعث میشود که SQL Server هر بار که کوئری اجرا میشود، یک Plan جدید بسازد و از Execution Plan ذخیرهشده قبلی استفاده نکند.
چرا لازم میشود؟
* وقتی دادهها یا پراکندگی دادهها (Data Distribution) خیلی متغیر هستند، استفاده از Plan قبلی ممکن است کارایی ضعیفی داشته باشد.
* مخصوصاً برای کوئریهایی که دارای پارامتر هستند و مقادیر پارامترهای مختلف باعث تغییر شدید تعداد ردیفها میشود.
مثال:
SELECT *
FROM Orders
WHERE CustomerID = @CustID
OPTION (RECOMPILE);
SQL Server هر بار که این کوئری اجرا شود، با مقدار واقعی @CustID Plan جدید میسازد.
2. OPTIMIZE FOR UNKNOWN
این گزینه به Optimizer میگوید فرض کند که هیچ اطلاعات خاصی از پارامترها ندارد و Plan را بر اساس آمار کلی جدول بسازد، نه بر اساس مقادیر واقعی پارامترها.
مزایا:
* وقتی دادهها خیلی نامتوازن هستند (مثلاً بعضی مقادیر پارامتر خیلی پرت هستند)، این گزینه از parameter sniffing problem جلوگیری میکند.
* به جای اینکه Plan برای یک مقدار خاص پارامتر بهینه شود، Planی عمومی ساخته میشود.
مثال:
SELECT *
FROM Orders
WHERE CustomerID = @CustID
OPTION (OPTIMIZE FOR UNKNOWN);
SQL Server از آماری استفاده میکند که برای تمام دادهها معتبر باشد، نه فقط مقدار @CustID.
نکته مهم:
میتوان این دو را با هم استفاده کرد:
SELECT *
FROM Orders
WHERE CustomerID = @CustID
OPTION (RECOMPILE, OPTIMIZE FOR UNKNOWN);
هر بار که کوئری اجرا شود، Plan جدید ساخته میشود و این Plan برای مقدار واقعی پارامتر بهینه نمیشود بلکه برای "مقدار ناشناخته" بهینهسازی میشود.
اگر با پیغام خطای زیر هنگام اجرای برنامه و ارتباط با SQL Server برخورد کردید:
SSL Provider, error: 0 - An existing connection was forcibly closed by the remote host
باید دستور زیر را در Power Shell وارد کنید:
Powershell in admin mode:
Enable-TlsCipherSuite -Name "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
declare @date as int
declare @day as int
declare @month as int
set @date=14030101
set @day=1
set @month=1
create table #tblDate (
[dt] int,
[myDay] int
);
while (@month<=12)
begin
insert into #tblDate (dt, myDay) values (@date, @day)
set @day = @day + 1
if (@month<7) and (@day>31)
begin
set @day= 1
set @month = @month + 1
set @date = @date + 70
end
else if (@month>6) and (@day>30)
begin
set @day= 1
set @month = @month + 1
set @date = @date + 71
end
else
set @date = @date + 1
end
delete from #tblDate where dt=(select top 1 dt from #tblDate order by dt desc)
select * from #tblDate
drop table #tblDate
SELECT DB_NAME(database_id),
COUNT (1) * 8 / 1024 AS MBUsed
FROM sys.dm_os_buffer_descriptors
GROUP BY database_id
ORDER BY COUNT (*) * 8 / 1024 DESC
GO