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

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

Описание команды SET STATISTICS IO

SET STATISTICS IO не является функцией в классическом понимании, это инструкция Transact-SQL, управляющая выводом статистической информации о активности дискового ввода-вывода для инструкций языка Transact-SQL. Её основное назначение — анализ производительности запросов, предоставление количественных данных о логических и физических операциях чтения данных с диска.

Использование этой инструкции актуально при профилировании и оптимизации запросов, когда необходимо оценить ресурсоёмкость операций и выявить узкие места, связанные с доступом к данным.

Инструкция принимает один параметр, который может находиться в двух состояниях:

  • ON: включает вывод статистики ввода-вывода. После активации для каждой последующей выполняемой команды в том же сеансе будет выводиться отдельное сообщение с метриками.
  • OFF: отключает вывод статистики. Это состояние установлено по умолчанию.

Результатом выполнения команды является не табличный набор данных, а текстовое сообщение в разделе 'Сообщения' среды SQL Server Management Studio. Оно содержит следующие ключевые метрики:

  • Таблица 'ИмяТаблицы': указывает обработанную таблицу.
  • число просмотров: количество логических операций чтения (логических чтений), выполненных с момента загрузки страницы данных в кэш буферного пула.
  • число логических чтений: часто совпадает с 'число просмотров' и также обозначает логические чтения.
  • число физических чтений: количество операций физического чтения с диска, когда требуемая страница не была найдена в буферном кэше.
  • число упреждающих чтений: отражает активность механизма упреждающего чтения, который асинхронно загружает страницы в кэш.
  • LOB-число логических чтений: логические чтения для страниц больших объектов (LOB), таких как TEXT, NTEXT, IMAGE, VARCHAR(MAX).
  • LOB-число физических чтений: физические чтения для страниц LOB.
  • LOB-число упреждающих чтений: упреждающие чтения для страниц LOB.

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

Пример включения статистики, выполнения простого запроса и её отключения.

SET STATISTICS IO ON;
GO

SELECT * FROM [Sales].[SalesOrderHeader] WHERE OrderDate > '2013-12-31';
GO

SET STATISTICS IO OFF;
GO
(31465 строк затронуто)

Таблица "SalesOrderHeader". Число просмотров = 1, число логических чтений = 689, число физических чтений = 0, число упреждающих чтений = 0, LOB-число логических чтений = 0, LOB-число физических чтений = 0, LOB-число упреждающих чтений = 0.

Пример, демонстрирующий разницу в статистике до и после создания индекса (симуляция).

SET STATISTICS IO ON;
GO
-- Запрос без подходящего индекса
SELECT CustomerID FROM [Sales].[SalesOrderHeader] WHERE SalesOrderNumber = 'SO43697';
GO
-- После условного создания индекса...
SELECT CustomerID FROM [Sales].[SalesOrderHeader] WHERE SalesOrderNumber = 'SO43697';
GO
SET STATISTICS IO OFF;
(1 строка затронута)
Таблица "SalesOrderHeader". Число просмотров = 1, число логических чтений = 689, число физических чтений = 0, ...

(1 строка затронута)
Таблица "SalesOrderHeader". Число просмотров = 1, число логических чтений = 3, число физических чтений = 0, ...

Похожие инструменты анализа в MS SQL Server

SET STATISTICS TIME: выводит данные о времени, затраченном на синтаксический анализ, компиляцию и выполнение каждого запроса. Используется совместно со STATISTICS IO для комплексного анализа производительности.

Динамические административные представления (DMV): предоставляют более структурированный и гибкий способ получения статистики. Например, sys.dm_exec_query_stats кэширует агрегированную статистику по планам выполнения, включая логические и физические операции ввода-вывода. Предпочтительны для программного анализа и мониторинга.

Расширенные события (Extended Events): предлагают низкоуровневую и настраиваемую систему сбора широкого спектра данных о выполнении запросов, включая события, связанные с вводом-выводом. Используются для глубокой диагностики сложных проблем.

SQL Server Profiler / Trace: устаревшие, но иногда используемые инструменты для трассировки событий сервера, включая события завершения запросов с показателями Reads и Writes, которые аналогичны логическим чтениям.

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

PostgreSQL: Используется команда EXPLAIN (ANALYZE, BUFFERS). Ключевое слово BUFFERS добавляет вывод информации о чтении буферов (аналог логических чтений). Разделение на физические/логические чтения менее явное.

EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE order_date > '2013-12-31';
...
Buffers: shared hit=523 read=689
...

Oracle: Статистику ввода-вывода можно получить, включив трассировку на уровне сессии командой ALTER SESSION SET STATISTICS_LEVEL = ALL; или используя хинт /*+ GATHER_PLAN_STATISTICS */, после чего запросить план выполнения из V$SQL_PLAN_STATISTICS_ALL. Более простой способ — использование SET AUTOTRACE TRACEONLY STATISTICS в SQL*Plus.

SET AUTOTRACE TRACEONLY STATISTICS;
SELECT * FROM scott.emp WHERE deptno = 10;
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          7  consistent gets
          0  physical reads
...

MySQL: Для анализа производительности запросов используется команда EXPLAIN ANALYZE (доступна с версии 8.0.18), которая выводит информацию о фактическом выполнении, включая итерации и стоимость, но без детализации по типу операций ввода-вывода, характерной для SQL Server. Более детальную статистику можно получить из Performance Schema или статус-переменных.

EXPLAIN ANALYZE SELECT * FROM orders WHERE order_date > '2013-12-31';
-> Filter: (orders.order_date > TIMESTAMP'2013-12-31 00:00:00')  (cost=... rows=... actual time=... rows=... loops=1)
    -> Table scan on orders  (cost=... rows=... actual time=... rows=... loops=1)

SQLite: Практически отсутствуют встроенные средства для получения детальной статистики ввода-вывода. Команда EXPLAIN QUERY PLAN показывает только логический план выполнения без метрик производительности.

Типичные ошибки и недопонимания

1. Интерпретация 'физических чтений' как текущей нагрузки на диск: Значение 'число физических чтений' может быть равно нулю при повторном выполнении запроса, так как данные уже находятся в кэше буферного пула. Для оценки реальной нагрузки на подсистему хранения необходим анализ первого выполнения после очистки кэша или перезапуска службы.

2. Игнорирование статистики для LOB-данных: При работе с большими полями (VARCHAR(MAX), VARBINARY(MAX)) основные метрики ('число логических чтений') могут не отражать полный объём работы. Необходимо отдельно анализировать строки 'LOB-число логических/физических чтений'.

3. Попытка получить результат в табличном виде: Вывод STATISTICS IO направляется только в поток сообщений. Его нельзя напрямую выбрать в таблицу с помощью SELECT. Для программной обработки требуется использовать альтернативы, такие как динамические административные представления (DMV), или парсить текст сообщений.

-- Неправильно: не вернёт статистику как результирующий набор.
SELECT * FROM (SET STATISTICS IO ON; SELECT 1 AS A) T;
Сообщение 156, уровень 15, состояние 1, строка 1
Неправильный синтаксис около ключевого слова 'SET'.

4. Сброс статистики кэша: Иногда для чистоты эксперимента пытаются сбросить кэш с помощью CHECKPOINT; DBCC DROPCLEANBUFFERS; на тестовом сервере. Важно помнить, что это действие влияет на всю базу данных и недопустимо в производственной среде.

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

Основной синтаксис и поведение SET STATISTICS IO остаются стабильными на протяжении многих версий. Однако, выходные данные были расширены с введением типов данных больших объектов (LOB).

В SQL Server 2012 и более поздних версиях формат вывода был дополнен строками, относящимися к операциям ввода-вывода для страниц LOB ('LOB-число логических чтений' и т.д.), что позволяет точнее анализировать запросы, работающие с большими данными.

Поведение и интерпретация метрик также зависят от архитектурных улучшений ядра СУБД, таких как изменения в алгоритмах упреждающего чтения или работа с колоночными индексами, но это не отражается на синтаксисе самой инструкции.

Расширенные примеры анализа

1. Сравнение эффективности различных типов соединений.

Пример sql
SET STATISTICS IO ON;
GO
-- Хэш-соединение (часто при отсутствии индексов)
SELECT *
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON sod.ProductID = p.ProductID;
GO
-- Вложенные циклы (чаще с индексами)
SELECT *
FROM Sales.SalesOrderDetail sod WITH (INDEX(IX_SalesOrderDetail_ProductID))
INNER JOIN Production.Product p ON sod.ProductID = p.ProductID;
GO
SET STATISTICS IO OFF;
-- Для первого запроса (Hash Match)
Таблица "Product". Число просмотров = 1, число логических чтений = 15, ...
Таблица "SalesOrderDetail". Число просмотров = 1, число логических чтений = 1246, ...

-- Для второго запроса (Nested Loops)
Таблица "Product". Число просмотров = 1, число логических чтений = 15, ...
Таблица "SalesOrderDetail". Число просмотров = 1, число логических чтений = 1, ... (для поиска по индексу)
Таблица "SalesOrderDetail". Число просмотров = 1, число логических чтений = 1216, ... (доп. чтения для вывода данных)

2. Анализ влияния выборки данных на статистику.

Пример sql
SET STATISTICS IO ON;
GO
-- Полное сканирование таблицы
SELECT COUNT(*) FROM [Production].[TransactionHistory];
GO
-- Поиск по индексу
SELECT COUNT(*) FROM [Production].[TransactionHistory] WHERE TransactionDate BETWEEN '2013-01-01' AND '2013-01-31';
GO
SET STATISTICS IO OFF;
-- Полное сканирование
Таблица "TransactionHistory". Число просмотров = 1, число логических чтений = 108, ...

-- Поиск по диапазону
Таблица "TransactionHistory". Число просмотров = 1, число логических чтений = 3, ... (чтение индексных страниц)
Таблица "TransactionHistory". Число просмотров = 1, число логических чтений = 2, ... (чтение данных по ключу)

3. Выявление проблем с параметризацией и 'прогревом' кэша.

Пример sql
-- Очистка кэша (ТОЛЬКО для тестового сервера!)
DBCC DROPCLEANBUFFERS;
GO

SET STATISTICS IO ON;
GO
-- Первый запуск с новым значением параметра
SELECT * FROM Sales.SalesOrderHeader WHERE CustomerID = 11000;
GO
-- Повторный запуск с тем же значением
SELECT * FROM Sales.SalesOrderHeader WHERE CustomerID = 11000;
GO
-- Запуск с другим значением (может использовать другой план)
SELECT * FROM Sales.SalesOrderHeader WHERE CustomerID = 30118;
GO
SET STATISTICS IO OFF;
-- Первый запуск: возможны физические чтения.
Таблица "SalesOrderHeader". ... число физических чтений = 45, ...

-- Второй запуск: все данные в кэше, физических чтений 0.
Таблица "SalesOrderHeader". ... число физических чтений = 0, ...

-- Третий запуск: статистика зависит от распределения данных и плана выполнения.

MS SQL SET STATISTICS IO function comments

En
SET STATISTICS IO Displays information about the amount of disk activity generated by Transact-SQL statements