Почему SYSDATETIME() не меняется при каждом вызове?

#sql-server #tsql

#sql-server #tsql

Вопрос:

Я пытаюсь проанализировать производительность запроса. К сожалению, у меня нет прав на выполнение расчетного или фактического плана запроса к базе данных, которую я читаю. ( SHOWPLAN в разрешении отказано в базе данных)

Я переписал исходный запрос, но хотел бы сравнить время выполнения исходного запроса и моих двух запросов. Для достижения этой цели я подумал, что создам 4 переменные datetime2 и буду записывать SYSDATETIME() между каждой итерацией, а затем находить разницу.

К сожалению, я обнаружил, что после вызова функция SYSDATETIME() не обновляется.

В общей сложности мои 3 запроса выполняются 17 секунд. Между каждым выполнением я должен иметь возможность видеть изменение временной метки, но переменные каждый раз записывают одну и ту же временную метку.

 declare @a datetime2, @b datetime2, @c datetime2, @d datetime2

set @a = SYSDATETIME()

select bunch of columns from a bunch of joined tables

set @b = SYSDATETIME()

select bunch of columns and sub-queries from a bunch of tables joined a little differently

set @c = SYSDATETIME()

select bunch of columns and sub-queries from a bunch of differently joined tables and sub-queries

set @d = SYSDATETIME()

print @a
print @b
print @c
print @d
  

Все 4 переменные имеют одинаковое значение.

 a   2019-04-05 16:00:09.3947421 
b   2019-04-05 16:00:09.3947421 
c   2019-04-05 16:00:09.3947421 
d   2019-04-05 16:00:09.3947421
  

Общее время выполнения составило 19 секунд, поэтому должны были быть действительные данные для проверки.

Есть предложения?

Комментарии:

1. предоставьте копию этого. Здесь нет повтора dbfiddle.uk /…

2. Может быть SQL распараллелен и ваши запросы выполняются не по порядку?

3. @Clay. no. parallelism в Sql Server так не работает.

Ответ №1:

Что ж, вместо того, чтобы записывать больше циклов, беспокоясь об этом, я просто напечатал временную метку и поставил ПЕРЕХОД между каждой итерацией моих тестов. Затем сделал математику позже.

Все еще не знаю, почему SYSDATETIME не возвращает истинное значение при каждом вызове. Возможно, SQL server пытается быть полезным.

К вашему сведению, из этого rtrim(ltrim(FIELD))) быстрее, чем ПОЛЕ типа ‘A%’, которое быстрее, чем FIELD = ‘A’, когда ПОЛЕ равно char(10).

Ответ №2:

Вероятно, весь запрос запускается одновременно.

Вместо этого попробуйте запускать каждый запрос отдельными пакетами. Это должно дать вам несколько полезных временных меток.

 declare @a datetime2 = SYSDATETIME()
print @a

go

select bunch of columns from a bunch of joined tables
declare @b datetime2 = SYSDATETIME()
print @b

go

select bunch of columns and sub-queries from a bunch of tables joined a little differently
DECLARE @c datetime2 = SYSDATETIME()
print @c

go

select bunch of columns and sub-queries from a bunch of differently joined tables and sub-queries
declare @d datetime2 = SYSDATETIME()
print @d

go
  

Комментарии:

1. SQL Server не выполняет разные инструкции в одном пакете одновременно. Одновременно может выполняться только один оператор. Вероятно, OP допустил какую-то ошибку, не показанную в коде, который они нам предоставили. (например, оставить там инструкцию, которая присваивает все переменные в одном операторе)

2. Нет, я ничего не упустил, и я не присваиваю всем переменным одинаковые значения сразу. Я занимаюсь SQL более десяти лет.

3. Это то, что я должен был сделать, Питер, спасибо. Но не объясняет, почему SQL не может быть обеспокоен возвращением истинного значения при каждом вызове функции.