Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Ai đó có thể giải thích sự khác biệt giữa hai truy vấn?

getdate() là một thời gian chạy hàm không đổi và chỉ được đánh giá một lần cho mỗi tham chiếu hàm, đó là lý do tại sao

SELECT GETDATE()
FROM SomeBigTable

sẽ trả về cùng một kết quả cho tất cả các hàng bất kể thời gian chạy truy vấn.

Tuy nhiên, có một sự khác biệt giữa cả hai. Vì kế hoạch đầu tiên sử dụng một biến và kế hoạch được biên dịch trước khi biến được gán cho SQL Server sẽ (trong trường hợp không có biên dịch lại) giả định rằng 30% số hàng sẽ được trả về. Phỏng đoán này có thể khiến nó sử dụng một kế hoạch khác với truy vấn thứ hai.

Cần lưu ý điều gì đó khi sử dụng GETDATE() trực tiếp trong bộ lọc là nó đánh giá GETDATE() tại thời điểm biên dịch và sau đó, độ chọn lọc có thể thay đổi đáng kể mà không cần truy vấn hoặc dữ liệu thay đổi để kích hoạt biên dịch lại. Trong ví dụ bên dưới đối với bảng 1.000 hàng, truy vấn sử dụng một biến dẫn đến một kế hoạch với ước tính 300 hàng và quét toàn bộ bảng trong khi truy vấn với lệnh gọi hàm được nhúng ước tính 1 hàng và thực hiện tra cứu dấu trang. Điều này chính xác trong lần chạy đầu tiên nhưng trong lần chạy thứ hai do thời gian trôi qua, giờ đây tất cả các hàng đều đủ điều kiện và kết thúc là 1.000 lần tìm kiếm ngẫu nhiên như vậy.

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. Làm cách nào để tìm tất cả trình kích hoạt được liên kết với một bảng với SQL Server?

  2. tập lệnh lạ do SQL Server tạo ra khi xuất công việc

  3. Liệt kê tất cả các cột không thể xóa trong cơ sở dữ liệu máy chủ SQL

  4. Ví dụ về DATEDIFF () trong SQL Server

  5. trả về giá trị tại một vị trí từ STRING_SPLIT trong SQL Server 2016