getdate()
adalah runtime fungsi konstan
dan hanya dievaluasi sekali per referensi fungsi, itulah sebabnya
SELECT GETDATE()
FROM SomeBigTable
akan mengembalikan hasil yang sama untuk semua baris terlepas dari berapa lama kueri dijalankan.
Namun ada perbedaan antara keduanya. Karena yang pertama menggunakan variabel dan rencana dikompilasi sebelum variabel ditetapkan ke SQL Server akan (jika tidak ada kompilasi ulang) mengasumsikan bahwa 30% dari baris akan dikembalikan. Tebakan ini dapat menyebabkannya menggunakan rencana yang berbeda dari kueri kedua.
Sesuatu yang perlu diingat dengan menggunakan GETDATE()
langsung dalam filter adalah bahwa ia mengevaluasi GETDATE()
pada waktu kompilasi dan setelah itu selektivitas dapat berubah secara dramatis tanpa kueri atau perubahan data untuk memicu kompilasi ulang. Dalam contoh di bawah ini terhadap tabel 1.000 baris, kueri yang menggunakan variabel mengarah ke rencana dengan perkiraan 300 baris dan pemindaian tabel penuh sedangkan kueri dengan panggilan fungsi yang disematkan memperkirakan 1 baris dan melakukan pencarian bookmark. Ini akurat pada putaran pertama tetapi pada putaran kedua karena berlalunya waktu sekarang semua baris memenuhi syarat dan akhirnya melakukan 1.000 pencarian acak seperti itu.
USE tempdb;
CREATE TABLE [myTable]
(
CreatedDate datetime,
Filler char(8000) NULL
)
CREATE NONCLUSTERED INDEX ix ON [myTable](CreatedDate)
INSERT INTO [myTable](CreatedDate)
/*Insert 1 row that initially qualifies*/
SELECT DATEADD(D,-2001,getdate())
UNION ALL
/*And 999 rows that don't initially qualify*/
SELECT TOP 999 DATEADD(minute,1, DATEADD(D,-2000,getdate()))
FROM master..spt_values
EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT *
FROM [myTable]
WHERE CreatedDate <= @myDate
')
EXEC('
SELECT *
FROM [myTable]
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')
RAISERROR ('Delay',0,1) WITH NOWAIT
WAITFOR DELAY '00:01:01'
EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT *
FROM [myTable]
WHERE CreatedDate <= @myDate
')
EXEC('
SELECT *
FROM [myTable]
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')
DROP TABLE [myTable]