Повышение скорости перестроения индекса на сервере SQL

9

Я импортирую большой объем данных в пустую базу данных, и перед тем как начать, я отключил все неуникальные некластеризованные индексы, чтобы посмотреть, смогу ли я улучшить производительность импорта.

Теперь я хочу снова включить индексы, и мне интересно, есть ли что-нибудь, что я могу сделать, чтобы оптимизировать это.

Необходимо перестроить более 100 таблиц и почти 2000 индексов. База данных имеет размер 200 ГБ.

Ключевой раздел скрипта, который я запускаю, таков:

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

Я рассмотрел установку ONLINE = OFF для оператора alter index, но поскольку индексы вначале отключены, я не был уверен, что этот параметр будет иметь какой-либо эффект. Я также рассмотрел возможность установки SORT_IN_TEMPDB = ON, но, поскольку файлы tempdb находятся на том же диске, что и файлы .mdf баз данных, я предположил, что это также не принесло пользы.

Во время выполнения сценария перестройки я заметил, что у меня много типов ожидания CXPACKET. Я не очень понимаю, почему это так или это проблема, которую я должен решить.

Последний момент, который может иметь значение: весь мой сервер в настоящее время неактивен, кроме импорта данных в базу данных. Нет других действий пользователя, чтобы рассмотреть или беспокоиться; моя единственная задача - импортировать данные в базу данных в кратчайшие сроки.

paulH
источник
3
Когда вы говорите, что вас беспокоит только время импорта, вы имеете в виду время от начала импорта до конца повторного включения индексов? Если это так, вы должны просто оставить индексы включенными во время импорта. 2000 индексов для 200 ГБ данных звучит для меня как множество индексов. Возможно, вам следует взглянуть на DMV использования индекса, чтобы увидеть, есть ли такие, которые можно удалить.
Макс Вернон,
1
Просто чтобы уточнить, вам нужно делать один и тот же импорт 200 ГБ несколько раз, а не один раз?
Джон Зигель,
1
Мне нужно выполнить импорт только один раз, но как часть более крупного процесса с ограниченным периодом времени, поэтому в настоящее время я тестирую этот процесс, чтобы он вписался в это окно. @MaxVernon Похоже, вы правы, что оставить индексы включенными - это самый быстрый способ, хотя я удивлен, когда узнал, что обычно отключать индексы обычно быстрее, импортировать данные, а затем снова включать индексы. Это сторонняя база данных, поэтому удаление индексов или иное изменение не представляется возможным.
paulH
3
Ладно. Об CXPACKETожиданиях: индекс перестраивает сами индексы сканирования (даже индекс перестраивается ), и эти сканирования могут использовать параллелизм. Вы не должны беспокоиться об этих ожиданиях - параллелизм, вероятно, помогает.
Джон Зигель

Ответы:

10

Достижение оптимальной производительности импорта в этом сценарии требует трех вещей:

  1. Минимально зарегистрированные каркасные таблицы вставок
  2. Построения минимально записанного некластерного индекса
  3. Избегать физического чтения

Минимальная регистрация

Для достижения минимально зарегистрированных журналов вставок в пустую кластеризованную таблицу без некластеризованных индексов необходимо:

  1. Использование моделей восстановления SIMPLEили BULK_LOGGEDбазы данных
  2. Указание блокировки таблицы и упорядоченного ввода (например, TABLOCKи ORDERподсказок)

Примечание:

Также возможно достичь минимально регистрируемых вставок в кластеризованную таблицу, которая имеет некластеризованные индексы, при условии, что включен флаг 610 трассировки. Независимо от того, внесены ли минимальные записи в некластеризованные индексы, зависит от плана запроса, выбранного оптимизатором запросов.

Если план запроса использует отдельный итератор для некластеризованного индекса, а для DMLRequestSortсвойства итератора установлено значение true, вставки некластеризованного индекса будут минимально регистрироваться при условии соблюдения других условий, упомянутых ранее.

Создание некластеризованных индексов отдельно

Преимущества этого:

  1. Кластерные индексные вставки могут быть минимально зарегистрированы без включения TF 610
  2. CREATE INDEX минимально регистрируется, если модель восстановления не FULL

Избегать физического чтения

В идеале импортируемые данные будут храниться на отдельном компьютере или, по крайней мере, на отдельном физическом хранилище, которое использовалось для размещения базы данных.

У сервера базы данных должно быть достаточно памяти для хранения самой большой базовой таблицы в кеше, и достаточно для операций сортировки, необходимых при построении некластеризованных индексов.

Хорошим примером является быстрая загрузка базовой таблицы (минимальная загрузка кластеризованного индекса), а затем построение всех некластеризованных индексов для этой таблицы, пока ее страницы данных все еще кэшируются.

Этот вопрос описывает процесс, при котором сначала загружаются базовые таблицы, а затем создаются некластеризованные индексы. Определение курсора не использует ORDER BYпредложение, чтобы по крайней мере сгруппировать построения некластеризованного индекса на одной и той же таблице вместе.

Вероятный результат заключается в том, что страницы данных для разных таблиц многократно считываются в кэш, а затем отбрасываются, поскольку некластеризованные индексы строятся в недетерминированном порядке.

Стоимость повторных физических чтений полностью доминирует над преимуществами минимального ведения журналов, получаемых при раздельном построении некластеризованных индексов. Это объясняет, почему вы обнаружили, что загрузка таблиц с существующими индексами происходит быстрее (поскольку все некластеризованные индексы для данной таблицы сохраняются перед переходом к следующей таблице).

Резюме

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

Вы могли бы также попытаться включить TF 610 перед загрузкой данных в таблицы с некластеризованными индексами уже на месте. Обычно это не так быстро, как в предыдущем методе, но может быть достаточно быстрым.

Для получения дополнительной информации смотрите следующее:

Руководство по производительности загрузки данных

Операции, которые могут быть минимально зарегистрированы

Пол Уайт 9
источник