Функции на SQL Server, които се считат за константи по време на изпълнение
се оценяват само веднъж. GETDATE()
е такава функция и DATEADD(..., constant, GETDATE())
също е константа по време на изпълнение. Като оставите действителното извикване на функцията вътре в заявката, вие позволявате на оптимизатора да види каква стойност действително ще бъде използвана (за разлика от снифинг на стойност на променлива) и след това той може да коригира съответно оценките си за кардиналност, евентуално да излезе с по-добър план.
Прочетете също това:Отстраняване на неизправности с лоша производителност на заявката:Постоянно сгъване и оценка на израза по време на оценка на кардиналността .
@Мартин Смит
Можете да изпълните тази заявка:
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;
В моя случай след 22 секунди той удари граничния случай и цикълът излезе. Важното е, че цикълът излезе с @cnt
нула . Човек би очаквал, че ако getdate()
се оценява на ред, тогава ще получим @cnt, различен от правилния @known брой, но не и 0. Фактът, че @cnt е нула, когато съществува цикъл, показва всеки getdate()
беше оценено веднъж и след това същата постоянна стойност беше използвана за всеки ред WHERE филтриране (не отговаря на нито един). Наясно съм, че един положителен пример не доказва теорема, но мисля, че случаят е достатъчно убедителен.