sql >> Database >  >> RDS >> Sqlserver

Kan iemand het verschil tussen twee queries uitleggen?

getdate() is een runtime constante functie en wordt slechts één keer geëvalueerd per functiereferentie, daarom

SELECT GETDATE()
FROM SomeBigTable

geeft hetzelfde resultaat voor alle rijen, ongeacht hoe lang het duurt om de query uit te voeren.

Er is echter een verschil tussen de twee. Aangezien de eerste een variabele gebruikt en het plan wordt gecompileerd voordat de variabele aan SQL Server wordt toegewezen, zal (bij afwezigheid van een hercompilatie) ervan uitgaan dat 30% van de rijen wordt geretourneerd. Deze gok kan ertoe leiden dat er een ander plan wordt gebruikt dan de tweede zoekopdracht.

Iets om in gedachten te houden bij het gebruik van GETDATE() direct in een filter is dat het GETDATE() . evalueert tijdens het compileren en daarna is het mogelijk dat de selectiviteit drastisch verandert zonder dat de query of de gegevens veranderen om een ​​hercompilatie te activeren. In het onderstaande voorbeeld tegen een tabel met 1.000 rijen leidt de query met behulp van een variabele tot een plan met naar schatting 300 rijen en een volledige tabelscan, terwijl de query met de ingesloten functieaanroep 1 rij schat en een bladwijzerzoekopdracht uitvoert. Dit is nauwkeurig bij de eerste run, maar vanwege het verstrijken van de tijd komen nu alle rijen bij de tweede run in aanmerking en worden er uiteindelijk 1.000 van dergelijke willekeurige zoekopdrachten uitgevoerd.

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]


  1. Bediening van MySQL . instellen

  2. Symfony3 - SQLSTATE [HY000] [2002] Geen dergelijk bestand of map

  3. Onderdruk waarschuwingsuitvoer in bash

  4. Hoe combineer je twee tabellen om dezelfde kolommen te bezitten?