← Назад к вопросам

Что такое фрагментация индексов в SQL?

2.3 Middle🔥 231 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое фрагментация индексов в SQL?

Фрагментация индексов — это явление, при котором логическая последовательность страниц индекса в SQL Server (и других СУБД) не соответствует их физическому порядку на диске, либо когда страницы индекса заполнены неэффективно (много пустого пространства). Это происходит из-за операций вставки, обновления и удаления данных, которые приводят к разрывам в структуре индекса.

Типы фрагментации

  1. Внешняя фрагментация (External Fragmentation):

    • Страницы индекса расположены в непоследовательном порядке на диске.
    • Возникает при операциях INSERT, UPDATE, DELETE, когда новые страницы выделяются в другом месте файла базы данных.
    • Пример: Страницы индекса должны идти в порядке 1, 2, 3, но физически размещены как 1, 5, 2.
  2. Внутренняя фрагментация (Internal Fragmentation):

    • На страницах индекса есть свободное пространство (пустые места).
    • Возникает при обновлениях, которые уменьшают размер строк, или при неполном заполнении страниц.
    • Пример: Страница рассчитана на 100% заполнения, но фактически занято только 60%.

Причины фрагментации

  • Частые операции DML: INSERT, UPDATE, DELETE нарушают упорядоченность данных.
  • Неправильный фактор заполнения (Fill Factor): Если FILLFACTOR установлен слишком низко, страницы изначально создаются с пустым пространством.
  • Отсутствие обслуживания индексов: Долгое время не выполняется перестроение или реорганизация индексов.

Как измерить фрагментацию

В SQL Server можно использовать системную функцию sys.dm_db_index_physical_stats:

SELECT 
    object_name(ips.object_id) AS TableName,
    i.name AS IndexName,
    ips.avg_fragmentation_in_percent,
    ips.page_count
FROM 
    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') ips
JOIN 
    sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE 
    ips.avg_fragmentation_in_percent > 10 -- Порог фрагментации
ORDER BY 
    ips.avg_fragmentation_in_percent DESC;

Последствия фрагментации

  • Снижение производительности запросов: SQL Server тратит больше времени на чтение данных с диска из-за неоптимального порядка страниц.
  • Увеличение нагрузки на диск: Операции ввода-вывода становятся менее эффективными.
  • Рост использования памяти: Фрагментированные индексы занимают больше места в кэше.

Как устранить фрагментацию

Основные методы:

  1. Реорганизация индекса (REORGANIZE):
    • Упорядочивает страницы индекса без их пересоздания.
    • Менее ресурсоемкая операция, выполняется онлайн (без блокировок таблицы).
    • Подходит для средней фрагментации (до 30%).
ALTER INDEX IX_Employee_Name ON Employees REORGANIZE;
  1. Перестроение индекса (REBUILD):
    • Полностью пересоздает индекс, устраняя внутреннюю и внешнюю фрагментацию.
    • Более ресурсоемкая операция, может требовать блокировок (но есть опция ONLINE).
    • Подходит для высокой фрагментации (более 30%).
-- Оффлайн перестроение
ALTER INDEX IX_Employee_Name ON Employees REBUILD;

-- Онлайн перестроение (SQL Server Enterprise)
ALTER INDEX IX_Employee_Name ON Employees REBUILD WITH (ONLINE = ON);

Профилактика фрагментации

  • Регулярное обслуживание индексов: Планируйте задачи перестроения/реорганизации (например, через Maintenance Plans).
  • Оптимизация FILLFACTOR: Устанавливайте значение, учитывающее частоту изменений данных (например, 80-90% для часто изменяемых таблиц).
  • Использование секционирования: Разделение больших таблиц на секции уменьшает воздействие фрагментации.
  • Мониторинг: Регулярно проверяйте уровень фрагментации критических индексов.

Пример автоматизации обслуживания

-- Пример скрипта для реорганизации/перестроения индексов
DECLARE @TableName NVARCHAR(128), @IndexName NVARCHAR(128), @Fragmentation FLOAT;

DECLARE index_cursor CURSOR FOR
SELECT 
    object_name(ips.object_id),
    i.name,
    ips.avg_fragmentation_in_percent
FROM 
    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN 
    sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE 
    ips.avg_fragmentation_in_percent > 15
    AND ips.page_count > 1000;

OPEN index_cursor;
FETCH NEXT FROM index_cursor INTO @TableName, @IndexName, @Fragmentation;

WHILE @@FETCH_STATUS = 0
BEGIN
    IF @Fragmentation > 30
        EXEC('ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REBUILD');
    ELSE
        EXEC('ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REORGANIZE');
    
    FETCH NEXT FROM index_cursor INTO @TableName, @IndexName, @Fragmentation;
END;

CLOSE index_cursor;
DEALLOCATE index_cursor;

Вывод: Фрагментация индексов — естественный процесс в активных базах данных, но ее необходимо контролировать. Регулярное обслуживание индексов — ключ к поддержанию высокой производительности SQL-сервера. Важно балансировать между затратами на обслуживание и выгодами от оптимизации, выбирая правильную стратегию (реорганизация vs перестроение) для каждого случая.