Я создал таблицу big_table по вашей схеме
create table big_table
(
updatetime datetime not null,
name char(14) not null,
TheData float,
primary key(Name,updatetime)
)
Затем я заполнил таблицу 50000 строк с этим кодом:
DECLARE @ROWNUM as bigint = 1
WHILE(1=1)
BEGIN
set @rownum = @ROWNUM + 1
insert into big_table values(getdate(),'name' + cast(@rownum as CHAR), cast(@rownum as float))
if @ROWNUM > 50000
BREAK;
END
Используя SSMS, я протестировал оба запроса и понял, что в первом запросе вы ищете MAX для TheData, а во втором - MAX для времени обновления
Таким образом, я изменил первый запрос, чтобы получить также максимум обновления
set statistics time on -- execution time
set statistics io on -- io stats (how many pages read, temp tables)
-- query 1
SELECT MAX([UpdateTime])
FROM big_table
-- query 2
SELECT MAX([UpdateTime]) AS value
from
(
SELECT [UpdateTime]
FROM big_table
group by [UpdateTime]
) as t
set statistics time off
set statistics io off
Используя статистическое время, я получаю количество миллисекунд, необходимое для анализа, компиляции и выполнения каждого оператора.
Используя статистику ввода / вывода, я получаю информацию о дисковой активности
STATISTICS TIME и STATISTICS IO предоставляют полезную информацию. Например, были использованы временные таблицы (указаны рабочим столом). Также, сколько прочитанных логических страниц было прочитано, что указывает на количество страниц базы данных, прочитанных из кэша.
Затем я активирую план выполнения с помощью CTRL + M (активирует показ фактического плана выполнения), а затем выполняю с помощью F5.
Это обеспечит сравнение обоих запросов.
Вот вывод вкладки « Сообщения»
- Запрос 1
Стол "большой_таблицы". Сканирование 1, логическое чтение 543 , физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.
Время выполнения SQL Server:
время ЦП = 16 мс, прошедшее время = 6 мс .
- Запрос 2
Стол « Рабочий стол ». Сканирование счетчик 0, логическое чтение 0, физическое чтение 0, чтение с опережением 0, логическое чтение с бита 0, физическое чтение с бита 0, чтение с опережением чтения 0.
Стол "большой_таблицы". Сканирование 1, логическое чтение 543 , физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.
Время выполнения SQL Server:
время ЦП = 0 мс, прошедшее время = 35 мс .
Оба запроса приводят к 543 логическим чтениям, но у второго запроса истекшее время 35 мс, тогда как у первого - только 6 мс. Вы также заметите, что второй запрос приводит к использованию временных таблиц в базе данных tempdb, обозначенных словом worktable . Несмотря на то, что все значения для рабочего стола равны 0, работа все еще выполнялась в базе данных tempdb.
Затем выводится вкладка фактического плана выполнения рядом с вкладкой «Сообщения».
Согласно плану выполнения, предоставленному MSSQL, второй предоставленный вами запрос имеет общую стоимость пакета 64%, тогда как первый запрос стоит всего 36% от общего пакета, поэтому первый запрос требует меньше работы.
Используя SSMS, вы можете тестировать и сравнивать свои запросы и точно выяснять, как MSSQL анализирует ваши запросы и какие объекты: таблицы, индексы и / или статистические данные, если таковые используются, для удовлетворения этих запросов.
Еще одно дополнительное замечание, которое следует учитывать при тестировании, - это очистить кеш перед тестированием, если это возможно. Это помогает гарантировать, что сравнения точны, и это важно, когда вы думаете об активности диска. Я начинаю с DBCC DROPCLEANBUFFERS и DBCC FREEPROCCACHE, чтобы очистить весь кэш. Однако будьте осторожны, чтобы не использовать эти команды на рабочем сервере, который фактически используется, поскольку вы фактически заставите сервер читать все данные с диска в память.
Вот соответствующая документация.
- Очистить кэш плана с помощью DBCC FREEPROCCACHE
- Очистить все из пула буферов с помощью DBCC DROPCLEANBUFFERS
Использование этих команд может быть невозможно в зависимости от того, как используется ваша среда.
Обновлено 28.10 12:46
Внесены исправления в изображение плана выполнения и вывод статистики.
getdate()
из цикла