sql >> Databasteknik >  >> RDS >> Sqlserver

Kan någon förklara skillnaden mellan två frågor?

getdate() är en runtime konstant funktion och utvärderas endast en gång per funktionsreferens vilket är anledningen

SELECT GETDATE()
FROM SomeBigTable

kommer att returnera samma resultat för alla rader oavsett hur lång tid det tar att köra frågan.

Det finns dock en skillnad mellan de två. Eftersom den första använder en variabel och planen kompileras innan variabeln tilldelas till SQL Server kommer (i avsaknad av en omkompilering) att anta att 30% av raderna kommer att returneras. Denna gissning kan göra att den använder en annan plan än den andra frågan.

Något att tänka på när du använder GETDATE() direkt i ett filter är att det utvärderar GETDATE() vid kompileringstid och därefter är det möjligt för selektiviteten att ändras dramatiskt utan att vare sig frågan eller data ändras för att utlösa en omkompilering. I exemplet nedan mot en tabell med 1 000 rader leder frågan som använder en variabel till en plan med uppskattningsvis 300 rader och en fullständig tabellskanning, medan frågan med funktionsanropet inbäddat uppskattar 1 rad och gör en bokmärkessökning. Detta är korrekt på den första omgången men på den andra omgången på grund av tidens gång kvalificerar nu alla rader och det slutar med att det gör 1 000 sådana slumpmässiga sökningar.

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. Migrera ett teckenbaserat Oracle-formulär

  2. Välj rader från MySQL-tabellen där PHP-tidsstämpeln är äldre än X

  3. Hur visar man bildalbum i inlägg? [använder endast PHP och MYSQL]

  4. Lista alla funktioner i Oracle Database