Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Czy ktoś mógłby wyjaśnić różnicę między dwoma zapytaniami?

getdate() jest środowiskiem uruchomieniowym funkcja stała i jest oceniany tylko raz na odwołanie do funkcji, dlatego

SELECT GETDATE()
FROM SomeBigTable

zwróci ten sam wynik dla wszystkich wierszy, niezależnie od tego, jak długo trwa zapytanie.

Jest jednak między nimi różnica. Ponieważ pierwszy korzysta ze zmiennej, a plan jest kompilowany przed przypisaniem zmiennej do SQL Server, przyjmie (w przypadku braku rekompilacji) zwrócenie 30% wierszy. To przypuszczenie może spowodować użycie innego planu niż drugie zapytanie.

Coś, o czym należy pamiętać przy użyciu GETDATE() bezpośrednio w filtrze jest to, że oblicza GETDATE() w czasie kompilacji i później istnieje możliwość radykalnej zmiany selektywności bez zmiany zapytania lub danych w celu wywołania ponownej kompilacji. W poniższym przykładzie w odniesieniu do tabeli zawierającej 1000 wierszy zapytanie używające zmiennej prowadzi do planu z szacowanymi 300 wierszami i pełnym skanowaniem tabeli, podczas gdy zapytanie z osadzonym wywołaniem funkcji szacuje 1 wiersz i wykonuje wyszukiwanie zakładek. Jest to dokładne w pierwszym przebiegu, ale w drugim przebiegu ze względu na upływ czasu teraz wszystkie wiersze kwalifikują się i kończy się to wykonaniem 1000 takich losowych wyszukiwań.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Przechowuj plik w bazie danych SQL Server przy użyciu .Net MVC3 z Entity Framework

  2. Błąd sqlserver_ado nie jest dostępnym zapleczem bazy danych (PyISAPIe w IIS)

  3. Jak mogę zoptymalizować/refaktoryzować klauzulę TSQL LIKE?

  4. Czasami pojawia się wyjątek SqlException:upłynął limit czasu

  5. Cofanie aktualizacji tabel w SQL Server 2008