Các hàm SQL Server được coi là hằng số thời gian chạy
chỉ được đánh giá một lần. GETDATE()
là một hàm như vậy và DATEADD(..., constant, GETDATE())
cũng là một hằng số thời gian chạy. Bằng cách để lệnh gọi hàm thực bên trong truy vấn, bạn cho phép trình tối ưu hóa xem giá trị nào sẽ thực sự được sử dụng (trái ngược với giá trị biến đổi) và sau đó nó có thể điều chỉnh ước tính số lượng của nó cho phù hợp, có thể đưa ra một kế hoạch tốt hơn.
Ngoài ra, hãy đọc phần này: Khắc phục sự cố Hiệu suất Truy vấn Kém:Đánh giá Biểu thức và Gấp Liên tục Trong Ước tính Cardinality .
@Martin Smith
Bạn có thể chạy truy vấn này:
set nocount on;
declare @known int;
select @known = count(*) from sysobjects;
declare @cnt int = @known;
while @cnt = @known
select @cnt = count(*) from sysobjects where getdate()=getdate()
select @cnt, @known;
Trong trường hợp của tôi sau 22 giây nó chạm vào trường hợp ranh giới và vòng lặp thoát ra. Điều quan trọng là vòng lặp đã thoát bằng @cnt
không . Người ta sẽ mong đợi rằng nếu getdate()
được đánh giá trên mỗi hàng thì chúng ta sẽ nhận được @cnt khác với số @known chính xác, nhưng không phải là 0. Thực tế là @cnt bằng 0 khi tồn tại vòng lặp hiển thị mỗi getdate()
đã được đánh giá một lần và sau đó, cùng một giá trị không đổi được sử dụng cho mỗi hàng WHERE lọc (không khớp với hàng nào). Tôi biết rằng một ví dụ tích cực không chứng minh một định lý, nhưng tôi nghĩ rằng trường hợp này đủ kết luận.