Диагностика перенаправленных записей в heap SQL Server
Измеряйте перемещения строк в куче SQL Server и связывайте их с чтениями и задержками до выбора перестроения или изменения структуры таблицы.
Куча может подходить для краткоживущих данных и вести себя иначе после месяцев обновлений. Когда строка переменной длины растет, исходной странице может не хватить места. SQL Server способен переместить строку, оставив перенаправление в старой позиции.
Воспроизвести рост в учебной таблице
Heap не имеет кластерного индекса, но может содержать некластерные. Поэтому пример явно задает некластерный первичный ключ, чтобы незаметно не изменить структуру. Используйте учебную базу, где указанное имя свободно.
CREATE TABLE dbo.HeapForwardDemo
(
RowId int NOT NULL PRIMARY KEY NONCLUSTERED,
Payload varchar(1000) NOT NULL
);
;WITH N AS
(
SELECT TOP (10000)
CONVERT(int, ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS n
FROM sys.all_objects AS a CROSS JOIN sys.all_objects AS b
)
INSERT dbo.HeapForwardDemo (RowId, Payload)
SELECT n, REPLICATE('a', 100) FROM N;
UPDATE dbo.HeapForwardDemo
SET Payload = REPLICATE('b', 900)
WHERE RowId % 2 = 0;
Исходное содержимое короткое, затем половина строк существенно расширяется. Число перенаправлений зависит от размещения и свободного места. Его нужно измерять, а не ожидать фиксированный процент.
SELECT
index_id, partition_number, alloc_unit_type_desc,
page_count, record_count,
forwarded_record_count,
avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats
(
DB_ID(), OBJECT_ID(N'dbo.HeapForwardDemo'), 0, NULL, 'DETAILED'
)
WHERE alloc_unit_type_desc = 'IN_ROW_DATA';
Проверка направлена на одну кучу и использует DETAILED. Физическая диагностика может потреблять значительный ввод-вывод и требует подходящих прав. Не заменяйте фильтр объекта на NULL в большой рабочей базе ради всеобъемлющего отчета.
forwarded_record_count подтверждает перемещения. page_count и средняя заполненность описывают остальное размещение. NULL в менее подробном режиме не означает нулевое количество. Сохраняйте режим, раздел и единицу распределения вместе с показателями.
Связать размещение с запросами
Некластерные индексы кучи используют локаторы, которые могут вести сначала к старому месту, затем к перенаправленной строке. Дополнительный переход способен увеличить работу, но один счетчик не измеряет пользовательскую задержку. Важны путь доступа, кэш и частота чтения.
Найдите затронутые запросы и запишите логические чтения, CPU, время и фактические планы для характерных параметров. Сравните похожую нагрузку. Если строки одновременно стали в девять раз шире, число страниц и меньшая плотность объясняют часть изменений независимо от перенаправлений.
Покрывающий некластерный индекс может избавить конкретный запрос от чтения некоторых данных кучи. Но он добавляет хранение и обслуживание записи, а другие запросы продолжают обращаться к базе. Выбирайте индексы по полезным сценариям, а не для сокрытия необъясненной проблемы.
Также различайте перенаправления и логическую фрагментацию B-tree. Регламент, использующий только avg_fragmentation_in_percent, может пропустить важное. Heap требует отдельной трактовки и связи с нагрузкой.
Выбрать действие по жизненному циклу
Перестроение может убрать существующие перенаправления, но не предотвращает новые расширяющие updates. Следующие команды касаются только учебного объекта. После перестроения повторите диагностику до удаления таблицы.
ALTER TABLE dbo.HeapForwardDemo REBUILD;
-- Run the inspection query again before removing the test table.
DROP TABLE dbo.HeapForwardDemo;
В рабочей базе планируйте длительность, емкость журнала, место, блокировки и влияние на некластерные индексы. Перестроение только одного такого индекса не переупорядочивает базовые строки кучи. Произвольный порог перенаправлений сам по себе не обосновывает большую операцию.
Удачный кластерный индекс может подходить постоянной таблице с частыми чтениями по ключу и изменениями. Но он меняет локаторы и добавляет компромиссы разделения страниц и ширины ключа. Выбирайте стабильный ключ по реальной работе.
Для staging, который загружают, обрабатывают и очищают, куча может оставаться правильным выбором. Обслуживание тогда следует партии данных. Для постоянно расширяющихся строк проверьте необходимость такого роста и последовательность записи.
Сопоставьте последующее измерение с запросами и повторным появлением проблемы. Если перенаправления быстро возвращаются, а задержка почти не меняется после rebuild, регулярная перестройка лечит симптом. Сохраняйте также возраст партии и объем updates между замерами. Полезно заранее определить, какой измеримый эффект оправдает следующий запуск обслуживания: снижение чтений нужного запроса, восстановление пропускной способности или освобождение действительно необходимого места. Тогда решение опирается на жизненный цикл таблицы, а не на один пугающий счетчик.
Техническая документация: Microsoft Learn: Heaps · Microsoft Learn: Index physical statistics · Microsoft Learn: ALTER TABLE.