Подтвердить что ты не робот

При использовании GETDATE() во многих местах лучше использовать переменную?

Чем лучше, я имею в виду, улучшает ли производительность некоторую немаргинальную сумму?

То есть каждый раз, когда я вызываю GETDATE(), какой объем работы делает сервер, чтобы вернуть это значение?

Если я использую GETDATE() во многих местах хранимой процедуры, должен ли я вместо этого создавать переменную для хранения даты транзакции?

declare @transDate datetime = GETDATE()

Данные по маркировке скамьи будут фантастическими.

РЕДАКТИРОВАТЬ. Я хочу уточнить: меня интересуют главным образом фактические различия в производительности между этими двумя возможностями и важно ли это.

4b9b3361

Ответ 1

[ПРИМЕЧАНИЕ. Если вы хотите уменьшить этот ответ, пожалуйста, оставьте комментарий, объясняющий, почему. Он уже многократно опущен, и, наконец, ypercube (спасибо) объяснил хотя бы одну причину. Я не могу удалить ответ, потому что он принят, поэтому вы можете также помочь его улучшить.]

Согласно этому обмену на Microsoft, GETDATE() переключился с константы в запросе на недетерминированный в SQL Server 2005. Оглядываясь назад, я не думаю, что это точно. Я думаю, что он был полностью недетерминирован до SQL Server 2005, а затем взломан во что-то, называемое "неопределенная константа выполнения" с SQL Server 2005. Более поздняя фраза действительно означает "константа в запросе".

GETDATE() определяется как однозначно и с гордостью недетерминированный, без квалификаторов.)

Увы, в SQL Server не детерминированность не означает, что функция оценивается для каждой строки. SQL Server действительно делает это излишне сложным и двусмысленным с очень небольшим количеством документации по этому вопросу.

На практике вызов функции оценивается, когда запрос выполняется не один раз, когда запрос компилируется, и его значение изменяется каждый раз, когда он вызывается. На практике GETDATE() оценивается только один раз для каждого выражения, где оно используется, - во время выполнения, а не времени компиляции. Тем не менее, Microsoft помещает rand() и getdate() в специальную категорию, называемую getdate() постоянными функциями времени исполнения. Напротив, Postgres не перескакивает через такие обручи, он просто вызывает функции, которые имеют постоянное значение при выполнении как "стабильный".

Несмотря на комментарий Мартина Смита, документация SQL Server просто не является явной в этом вопросе - GETDATE() описывается как "недетерминированная" и " GETDATE() константа времени выполнения", но этот термин на самом деле не объясняется. В одном месте, где я нашел этот термин, например, следующие строки в документации говорят о том, что нельзя использовать недетерминированные функции в подзапросах. Это было бы глупым советом для "недетерминированной постоянной времени выполнения".

Я бы предложил использовать переменную с константой даже внутри запроса, поэтому у вас есть постоянное значение. Это также делает намерение совершенно ясным: вы хотите получить одно значение внутри запроса. В одном запросе вы можете сделать что-то вроде:

select . . . 
from (select getdate() as now) params cross join
     . . . 

На самом деле это предложение, которое должно оценивать только один раз в запросе, но могут быть исключения. Путаница возникает из-за getdate() что getdate() возвращает одно и то же значение во всех разных строках, но может возвращать разные значения в разных столбцах. Каждое выражение с getdate() оценивается независимо. Это очевидно, если вы запустите:

select rand(), rand()
from (values (1), (2), (3)) v(x);

В хранимой процедуре вы хотели бы иметь одно значение в переменной. Что произойдет, если хранимая процедура запускается с пропуском в полночь, а дата меняется? Какое влияние это оказывает на результаты?

Что касается производительности, то я предполагаю, что поиск по дате/времени минимален, и запрос возникает один раз для каждого выражения при запуске запроса. На самом деле это не проблема производительности, а скорее проблема согласованности кода.

Ответ 2

Мое предложение состояло в том, чтобы использовать переменную главным образом потому, что если у вас длительный процесс, значение GetDate() может отличаться от вызовов.

Если вы используете только часть Date GetDate(), тогда вы будете уверены, что всегда используете одно и то же значение.

Ответ 3

Одной из причин использования переменной с getdate() или таких функций, как suser_sname(), является огромная разница в производительности, если вы вставляете строки или выполняете GROUP BY. Вы заметите это, если вы вставляете большое количество строк.

Мне пришлось перенести 300 ГБ данных на несколько таблиц.

Ответ 4

Я тестировал несколько хранимых процедур, используя функцию GETDATE() в качестве переменной в SP, и у меня увеличивалось время чтения-ввода-вывода и время выполнения из-за того, что оптимизатор запросов не знает, какое значение для операции читает это Выполнение хранимой процедуры с параметрами, переменными и литералами, при этом вы можете использовать функцию GETDATE() в каждой отдельной части SP, поскольку @Gordon Linoff упомянул, что ее значение не изменяется во время выполнения или чтобы избежать/убрать мысль о том, что значение может измениться, я создал параметры следующим образом:

CREATE PROC TestGetdate
(
@CurrentDate DATETIME = NULL
)
AS
SET CurrentDate  = GETDATE()

..... а затем используйте параметры по своему усмотрению, вы увидите хорошие результаты

Любые комментарии или предложения приветствуются.

Ответ 5

Я использовал

WHERE ActualDateShipped+30 > dbo.Today()

в сочетании с функцией ниже. Привело мое время запроса с 13 секунд до 2 секунд. Никакие предыдущие ответы в этом сообщении не помогли этой проблеме в SQL 2008/R2.

CREATE FUNCTION [dbo].[Today]()

    RETURNS date
    AS
    BEGIN

        DECLARE @today date = getdate()

        RETURN @today
    End