
Инструкция SET STATISTICS TIME ON позволяет нам легко получить информацию о времени выполнения запроса. В этой статье посмотрим подробнее, какую именно, и что она означает.
Введение
В современном мире пользователи ожидают от приложений максимальной производительности, поэтому наши запросы должны быть очень быстрыми. А в оптимизации запросов помогает измерение их основных параметров производительности и, в этом контексте, SET STATISTICS TIME ON предоставляет нам простой, но очень полезный отчет о времени выполнения запроса.
Измерение времени выполнения запроса
Инструкция SET STATISTICS TIME ON отображает текстовый отчет с информацией о времени компиляции и общем времени выполнения запроса. Для его отображения необходимо перед запросом выполнить команду SET STATISTICS TIME ON, а для отключения — SET STATISTICS TIME OFF. Результат отображается на вкладке Messages (Сообщения). Все значения в миллисекундах.
Давайте включим отображение этой статистики и выполним запрос, приведенный ниже. (Примечание переводчика: используется база данных AdventureWorks.)
SET STATISTICS TIME ON;
GO
SELECT soh.[SalesPersonID],
p.[FirstName] + ' ' + COALESCE(p.[MiddleName], '') + ' ' + p.[LastName] AS [FullName],
e.[JobTitle],
st.[Name] AS [SalesTerritory],
soh.[SubTotal],
YEAR(DATEADD(m, 6, soh.[OrderDate])) AS [FiscalYear]
FROM [Sales].[SalesPerson] sp
INNER JOIN [Sales].[SalesOrderHeader] soh ON sp.[BusinessEntityID] = soh.[SalesPersonID]
INNER JOIN [Sales].[SalesTerritory] st ON sp.[TerritoryID] = st.[TerritoryID]
INNER JOIN [HumanResources].[Employee] e ON soh.[SalesPersonID] = e.[BusinessEntityID]
INNER JOIN [Person].[Person] p ON p.[BusinessEntityID] = sp.[BusinessEntityID];
GO

Для более удобного представления результатов вы можете использовать Statistics Parser.

Parse and compile time (время синтаксического анализа и компиляции)
Выполнение запроса в SQL Server начинается с синтаксического анализа (проверка синтаксиса), с последующей компиляцией (генерация оптимального плана выполнения запроса). Время, затраченное на эти два этапа, отображается в разделе "SQL Server parse and compile time" (Время синтаксического анализа и компиляции SQL Server).
CPU time (время ЦП) — время процессора на синтаксический анализ и компиляцию.
Elapsed time (истекшее время) — общее время, затраченное на синтаксический анализ и компиляцию запроса. Включает в себя время процессора. Это значение также можно увидеть в плане запроса в атрибуте CompileTime оператора SELECT.

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

Однако в плане выполнения в атрибуте CompileTime все еще 32 мс — это время последней компиляции плана.
Execution Times (время работы)
В разделе SQL Server Execution Times (Время работы SQL Server) указано время, затраченное SQL server на выполнение скомпилированного плана запроса.
CPU time (Время ЦП) — время, затраченное процессором (процессорами). Elapsed time (затраченное время) — общее время выполнения запроса. Это время включает в себя все операции ввода-вывода, время ожидания и время, необходимое для отправки результата клиенту. Давайте проверим это. Включим фактический план выполнения и выполним следующий запрос.
SET STATISTICS TIME ON;
GO
SELECT * FROM sales.Store
INNER JOIN sales.Customer ON sales.Store.BusinessEntityID = sales.Customer.StoreID
INNER JOIN sales.SalesOrderHeader ON sales.Customer.CustomerID = sales.SalesOrderHeader.CustomerID
INNER JOIN sales.SalesOrderDetail ON sales.SalesOrderHeader.SalesOrderID = sales.SalesOrderDetail.SalesOrderID

Время синтаксического анализа и компиляции (SQL Server parse and compile time) равно нулю, так как запрос был найден в кэше. Общее время выполнения запроса (elapsed time) 3 823 мс, из них 562 мс — время процессора. Какие были ожидания можно увидеть в плане выполнения в свойстве WaitStats
оператора SELECT. Для нашего примера это ASYNC_NETWORK_IO.

Для того чтобы убрать время пересылки результатов клиенту, в нашем случае, в SQL Server Management Studio (SSMS), отключим отображение результатов запроса, включив параметр "Discard results after the execution" (Отбросить результаты после выполнения).

Откроем новую вкладку в SSMS и выполним тот же запрос.

Видно, что время ожидания было добавлено к затраченному времени (elapsed time).
Иногда можно встретить ситуацию, когда CPU time (Время ЦП) больше, чем elapsed time (затраченное время). Например, в следующем запросе.
SET STATISTICS TIME ON
GO
SELECT ProductID,SUM(LineTotal) AS TotalsOfLine ,
SUM(UnitPrice) AS TotalsOfPrice, SUM(UnitPriceDiscount) AS TotalsOfDiscount FROM
Sales.SalesOrderDetail SOrderDet
INNER JOIN Sales.SalesOrderHeader SalesOr
ON SOrderDet.SalesOrderID = SalesOr.SalesOrderID
WHERE PurchaseOrderNumber LIKE 'PO%'
GROUP BY ProductID

В плане выполнения у оператора SELECT мы видим атрибут Degree of Parallelism
, который указывает, сколько процессоров использовалось для обработки запроса. Видим, что использовалось несколько процессоров, поэтому суммарное CPU time
больше elapsed time
(затраченного). Еще один атрибут, связанный с параллельной обработкой запросов, — ThreadStat
. ThreadStat
показывает, сколько потоков было зарезервировано и использовано.

Резюме
В этой статье мы узнали, как использовать SET STATISTICS TIME ON и как интерпретировать его результаты.
Материал подготовлен в рамках курса «MS SQL Server Developer». Всех желающих приглашаем на открытый урок «SQL Server — подходы к управлению версиями баз данных». На этом занятии поговорим о вариантах версионирования структуры БД для SQL Server, использовании систем контроля версий и миграциях.