SET STATISTICS TIME: примеры (SQL)

Использование SET STATISTICS TIME для оценки производительности T-SQL
Раздел: Функции настройки и конфигурации, Статистика
SET STATISTICS TIME(ON | OFF): N/A

Описание функции SET STATISTICS TIME

SET STATISTICS TIME представляет собой не функцию, а инструкцию уровня сеанса в Microsoft SQL Server. Её применяют для вывода информации о времени, затраченном на синтаксический анализ, компиляцию и выполнение каждого оператора в пакете или хранимой процедуре.

Когда используется:

  • Профилирование и оптимизация производительности запросов.
  • Сравнение времени выполнения различных вариантов одного запроса.
  • Выявление этапов (компиляция vs выполнение), потребляющих наибольшие ресурсы времени.
  • Настройка индексов и оценка их влияния на скорость работы.

Аргументы и режимы:

Инструкция не принимает аргументов в традиционном смысле, но управляется двумя ключевыми словами:

  • SET STATISTICS TIME ON — активирует вывод статистики по времени для текущего сеанса.
  • SET STATISTICS TIME OFF — отключает вывод статистики (режим по умолчанию).

Возвращаемые значения:

Статистика не возвращается как результат запроса, а выводится в виде отдельного сообщения на вкладке «Сообщения» в SQL Server Management Studio (SSMS). Информация включает:

  • Время синтаксического анализа и компиляции SQL Server: Длительность, которую SQL Server потратил на разбор запроса, его оптимизацию и создание плана выполнения.
  • Время выполнения SQL Server: Фактическое время, затраченное ядром СУБД на выполнение запроса. Оно не включает время передачи данных клиенту.
  • Значения выводятся в миллисекундах (мс).

Примеры использования SET STATISTICS TIME

Пример 1: Базовая активация и простой запрос.

SET STATISTICS TIME ON;

SELECT *
FROM sys.objects
WHERE type = 'U';
Время синтаксического анализа и компиляции SQL Server: 
   Время ЦП = 0 мс, истекшее время = 4 мс.

Время выполнения SQL Server:
   Время ЦП = 0 мс, истекшее время = 12 мс.

Пример 2: Сравнение двух запросов в одном пакете.

SET STATISTICS TIME ON;

-- Запрос 1
SELECT COUNT(*) FROM Sales.SalesOrderHeader;

-- Запрос 2
SELECT COUNT(DISTINCT CustomerID) FROM Sales.SalesOrderHeader;
(строки COUNT) ...

Время выполнения SQL Server:
   Время ЦП = 16 мс, истекшее время = 22 мс.

(строки COUNT DISTINCT) ...

Время выполнения SQL Server:
   Время ЦП = 31 мс, истекшее время = 35 мс.

Пример 3: Использование в хранимой процедуре.

SET STATISTICS TIME ON;

EXEC dbo.usp_GetCustomerOrders @CustomerID = 11000;
Время синтаксического анализа и компиляции SQL Server: 
   Время ЦП = 0 мс, истекшее время = 0 мс.

(результаты процедуры)

Время выполнения SQL Server:
   Время ЦП = 10 мс, истекшее время = 15 мс.

Похожие средства в MS SQL Server

  • SET STATISTICS IO ON — выводит статистику по дисковому вводу-выводу (логические и физические чтения). Используется совместно со STATISTICS TIME для комплексного анализа. Помогает выявить проблемы с индексами.
  • Временные метки (timestamp) с помощью SYSDATETIME(). Позволяют вручную измерять время выполнения участков кода внутри пакета с более высокой гибкостью, но требует написания дополнительного кода.
  • Динамические административные представления (DMV), например, sys.dm_exec_query_stats. Содержат агрегированную статистику по выполненным запросам, включая время ЦП и общее время. Полезны для ретроспективного анализа, но не для разового измерения.
  • SQL Server Profiler / Extended Events — мощные инструменты трассировки событий сервера, включая длительность выполнения запросов (событие SQL:BatchCompleted). Применяются для мониторинга в производственной среде.

Предпочтения: Для быстрой разовой проверки одного запроса достаточно STATISTICS TIME. Для глубокой настройки индексов необходим STATISTICS IO. Для постоянного мониторинга производительности подходят Extended Events.

Аналоги в других СУБД

PostgreSQL

EXPLAIN ANALYZE SELECT * FROM pg_catalog.pg_tables;
QUERY PLAN
Seq Scan on pg_tables  (cost=0.00..1.30 rows=30 width=448) (actual time=0.010..0.023 rows=30 loops=1)
Planning Time: 0.060 ms
Execution Time: 0.042 ms

Особенность: EXPLAIN ANALYZE не только показывает время (Planning и Execution Time), но и выполняет запрос, выводя подробный план.

MySQL / MariaDB

SET PROFILING = 1;
SELECT * FROM information_schema.tables LIMIT 5;
SHOW PROFILES;
Query_ID | Duration   | Query
1        | 0.00020375 | SELECT * FROM information_schema.tables LIMIT 5

Особенность: Профилирование включается отдельно и сохраняет историю нескольких запросов.

Oracle

SET TIMING ON
SELECT COUNT(*) FROM user_tables;
COUNT(*)
--------
45

Elapsed: 00:00:00.01

Особенность: SET TIMING ON выводит общее время выполнения запроса. Более детальная статистика доступна через представления V$SQL с полями ELAPSED_TIME и CPU_TIME.

SQLite

.timer ON
SELECT * FROM sqlite_master;

Особенность: Режим .timer ON выводит время выполнения каждого запроса в консоли. Нет разделения на фазы компиляции и выполнения.

Распространенные ошибки

  • Интерпретация «истекшего времени» как времени, затраченного только сервером. На него влияет нагрузка на ЦП и другие процессы. «Время ЦП» — более стабильный показатель для сравнений.
    SET STATISTICS TIME ON;
    -- Выполняется при высокой нагрузке на сервер
    WAITFOR DELAY '00:00:01'; -- Имитация работы
    Время выполнения SQL Server:
       Время ЦП = 0 мс, истекшее время = 1002 мс.

    Истекшее время значительно больше времени ЦП из-за ожидания.

  • Запуск только один раз для «холодного» кэша. Первое выполнение включает время компиляции и заполнения кэша данных. Для объективного сравнения производительности запрос следует выполнять несколько раз после «прогрева».
    SET STATISTICS TIME ON;
    -- Первый запуск после очистки кэша
    DBCC DROPCLEANBUFFERS;
    DBCC FREEPROCCACHE;
    SELECT * FROM LargeTable;
    Время синтаксического анализа и компиляции SQL Server: 
       Время ЦП = 15 мс, истекшее время = 25 мс.
    Время выполнения SQL Server:
       Время ЦП = 250 мс, истекшее время = 1200 мс.
    
    -- Повторный запуск того же запроса
    SELECT * FROM LargeTable;
    Время синтаксического анализа и компиляции SQL Server: 
       Время ЦП = 0 мс, истекшее время = 0 мс.
    Время выполнения SQL Server:
       Время ЦП = 50 мс, истекшее время = 300 мс.

Изменения в последних версиях

Инструкция SET STATISTICS TIME остается неизменной на протяжении многих версий SQL Server с точки зрения синтаксиса и базового поведения. Однако, контекст её использования эволюционирует:

  • В SQL Server 2016 и выше с появлением Query Store у администраторов появился более удобный и мощный инструмент для исторического анализа производительности запросов, включая стабильно собираемую статистику по времени выполнения и использованию ресурсов.
  • Интеграция с расширенными событиями (Extended Events) предлагает более легковесную и настраиваемую альтернативу для трассировки по сравнению с устаревающим SQL Server Profiler, где также можно отслеживать события, связанные со временем выполнения.
  • Сам вывод статистики стал точнее отображать информацию в средах с несколькими ядрами ЦП и в виртуализированных средах, но формат сообщений не претерпел существенных изменений.

Расширенные примеры использования

Пример 1: Анализ разницы между временем компиляции при использовании параметризованного и непараметризованного запроса.

Пример sql
SET STATISTICS TIME ON;

-- Непараметризованный запрос (компиляция при каждом вызове)
DECLARE @i INT = 1;
WHILE @i <= 3
BEGIN
    EXEC('SELECT * FROM Sales.SalesOrderDetail WHERE SalesOrderID = ' + CAST(@i AS VARCHAR));
    SET @i += 1;
END;

-- Параметризованный запрос (план может быть кэширован и повторно использован)
DECLARE @j INT = 1;
WHILE @j <= 3
BEGIN
    SELECT * FROM Sales.SalesOrderDetail WHERE SalesOrderID = @j;
    SET @j += 1;
END;

В сообщениях будет видно, что для первого цикла время синтаксического анализа и компиляции > 0 мс для каждого выполнения. Для второго цикла компиляция, вероятно, произойдет только при первом выполнении.

Пример 2: Сравнение производительности разных методов соединения.

Пример sql
SET STATISTICS TIME ON;
SET STATISTICS IO ON; -- Добавляем для комплексного анализа

-- INNER JOIN
SELECT p.Name, sod.LineTotal
FROM Production.Product p
INNER JOIN Sales.SalesOrderDetail sod ON p.ProductID = sod.ProductID
WHERE p.Color = 'Red';

-- EXISTS
SELECT p.Name, p.ListPrice
FROM Production.Product p
WHERE p.Color = 'Red'
AND EXISTS (
    SELECT 1 FROM Sales.SalesOrderDetail sod WHERE sod.ProductID = p.ProductID
);

В результатах на вкладке «Сообщения» можно сравнить не только время выполнения (TIME), но и логические чтения (IO) для двух семантически схожих запросов.

Пример 3: Использование внутри транзакции для измерения времени операций изменения данных.

Пример sql
SET STATISTICS TIME ON;

BEGIN TRANSACTION;
    UPDATE Sales.SalesOrderHeader
    SET ShipDate = DATEADD(day, 1, ShipDate)
    WHERE SalesOrderID BETWEEN 43660 AND 43670;

    DELETE FROM Sales.SalesOrderDetail
    WHERE SalesOrderID = 43659;

ROLLBACK TRANSACTION; -- Откатываем изменения для чистоты теста
Время выполнения SQL Server:
   Время ЦП = 0 мс, истекшее время = 5 мс.

Время выполнения SQL Server:
   Время ЦП = 0 мс, истекшее время = 2 мс.

Это позволяет измерить время DML-операций без внесения изменений в базу данных.

MS SQL SET STATISTICS TIME function comments

En
SET STATISTICS TIME Displays the number of milliseconds required to parse, compile, and execute each statement