Измерение производительности запросов: «Стоимость плана выполнения» против «Затраченного времени»
Описание проблемы для StackOverflow.com:
Я пытаюсь определить относительную производительность двух различных запросов и у меня есть два способа измерения этого:
- Запустить оба запроса и измерить время выполнения каждого.
- Запустить оба запроса и получить "Стоимость Запроса" из фактического плана выполнения.
Вот код, который я использую для измерения времени выполнения запросов:
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
DECLARE @start DATETIME SET @start = getDate()
EXEC test_1a
SELECT getDate() - @start AS Execution_Time
GO
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
DECLARE @start DATETIME SET @start = getDate()
EXEC test_1b
SELECT getDate() - @start AS Execution_Time
GO
Вот что я получаю:
Stored_Proc Execution_Time Query Cost (Relative To Batch)
test_1a 1.673 seconds 17%
test_1b 1.033 seconds 83%
Результаты времени выполнения напрямую противоречат результатам Стоимости Запроса, и я испытываю затруднения с пониманием того, что на самом деле означает "Стоимость Запроса". Мой лучший предположение состоит в том, что это агрегат чтений/записей/времени ЦП и т.д. Поэтому у меня есть несколько вопросов:
- Существует ли какой-либо достоверный источник, который объясняет, что означает эта мера?
- Какие другие метрики "Производительности Запросов" используют люди, и каковы их относительные достоинства?
Важно отметить, что это средний SQL Server, работающий на MS SQL Server 2005 на MS Server 2003 Enterprise Edition с несколькими процессорами и 100+ одновременными пользователями.
Изменение:
После некоторых усилий мне удалось получить доступ к Profiler на этом SQL Server, и я могу предоставить дополнительную информацию (которая подтверждает связь между Стоимостью Запроса и системными ресурсами, а не временем выполнения):
Stored_Proc CPU Reads Writes Duration
test_1a 1313 3975 93 1386
test_1b 2297 49839 93 1207
Впечатляет, что использование большего количества ЦП и гораздо большего количества чтений занимает меньше времени 😃
3 ответ(ов)
Профайлер дает понимание ситуации.
- Запрос A: 1.3 секунды CPU, 1.4 секунды продолжительность
- Запрос B: 2.3 секунды CPU, 1.2 секунды продолжительность
Запрос B использует параллелизм: время CPU > продолжительность, например, запрос использует 2 процессора, в среднем по 1.15 секунды каждый.
Запрос A, вероятно, не использует параллелизм: CPU < продолжительность.
Это объясняет стоимость относительно пакета: 17% для более простого, непараллельного плана запроса.
Оптимизатор определяет, что запрос B более затратный и будет иметь выгоду от параллелизма, даже несмотря на дополнительные затраты на его выполнение.
Однако, стоит помнить, что запрос B использует 100% двух процессоров (то есть 50% для четырех процессоров) в течение примерно одной секунды. Запрос A использует 100% одного процессора в течение 1.5 секунд.
Пиковая нагрузка для запроса A ниже, однако это сказывается на увеличении продолжительности. С одним пользователем это не критично, а вот с 100 пользователями может иметь значение...
Для выполнения SQL-запроса, который вы привели, используется команда SET STATISTICS TIME ON
, чтобы получить информацию о времени выполнения запроса. В вашем случае запрос извлекает все записи из таблицы Production.ProductCostHistory
, где значение StandardCost
меньше 500.00.
Такой запрос будет выглядеть следующим образом:
SET STATISTICS TIME ON
SELECT *
FROM Production.ProductCostHistory
WHERE StandardCost < 500.00;
SET STATISTICS TIME OFF;
После выполнения этого запроса на вкладке "Messages" будет выведена информация о времени выполнения, которая может выглядеть так:
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 10 ms.
(778 row(s) affected)
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
В этом примере мы видим, что затраты по CPU составили 0 мс, а общее время выполнения запроса — 10 мс. Было затронуто 778 строк, и время анализа и компиляции запроса также составляет 0 мс.
Обратите внимание, что фактические значения времени могут варьироваться в зависимости от нагрузки на сервер и других факторов.
Чтобы включить отображение времени выполнения запроса, используйте команду SET STATISTICS TIME ON
перед вашим запросом.
После выполнения запроса в окне результатов перейдите на вкладку "Сообщение" (Messages). Там вы сможете увидеть время, затраченное на выполнение вашего запроса.
"Вставка результатов хранимой процедуры в временную таблицу"
Как выполнить оператор UPDATE с JOIN в SQL Server?
Выбор COUNT(*) с DISTINCT
Запрос UPDATE в SQL с использованием JOINов
with(nolock) или (nolock) - есть ли разница?