Я импортирую большой объем данных в пустую базу данных, и перед тем как начать, я отключил все неуникальные некластеризованные индексы, чтобы посмотреть, смогу ли я улучшить производительность импорта.
Теперь я хочу снова включить индексы, и мне интересно, есть ли что-нибудь, что я могу сделать, чтобы оптимизировать это.
Необходимо перестроить более 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. Я не очень понимаю, почему это так или это проблема, которую я должен решить.
Последний момент, который может иметь значение: весь мой сервер в настоящее время неактивен, кроме импорта данных в базу данных. Нет других действий пользователя, чтобы рассмотреть или беспокоиться; моя единственная задача - импортировать данные в базу данных в кратчайшие сроки.
CXPACKET
ожиданиях: индекс перестраивает сами индексы сканирования (даже индекс перестраивается ), и эти сканирования могут использовать параллелизм. Вы не должны беспокоиться об этих ожиданиях - параллелизм, вероятно, помогает.Ответы:
Достижение оптимальной производительности импорта в этом сценарии требует трех вещей:
Минимальная регистрация
Для достижения минимально зарегистрированных журналов вставок в пустую кластеризованную таблицу без некластеризованных индексов необходимо:
SIMPLE
илиBULK_LOGGED
базы данныхTABLOCK
иORDER
подсказок)Примечание:
Создание некластеризованных индексов отдельно
Преимущества этого:
CREATE INDEX
минимально регистрируется, если модель восстановления неFULL
Избегать физического чтения
В идеале импортируемые данные будут храниться на отдельном компьютере или, по крайней мере, на отдельном физическом хранилище, которое использовалось для размещения базы данных.
У сервера базы данных должно быть достаточно памяти для хранения самой большой базовой таблицы в кеше, и достаточно для операций сортировки, необходимых при построении некластеризованных индексов.
Хорошим примером является быстрая загрузка базовой таблицы (минимальная загрузка кластеризованного индекса), а затем построение всех некластеризованных индексов для этой таблицы, пока ее страницы данных все еще кэшируются.
Этот вопрос описывает процесс, при котором сначала загружаются базовые таблицы, а затем создаются некластеризованные индексы. Определение курсора не использует
ORDER BY
предложение, чтобы по крайней мере сгруппировать построения некластеризованного индекса на одной и той же таблице вместе.Вероятный результат заключается в том, что страницы данных для разных таблиц многократно считываются в кэш, а затем отбрасываются, поскольку некластеризованные индексы строятся в недетерминированном порядке.
Стоимость повторных физических чтений полностью доминирует над преимуществами минимального ведения журналов, получаемых при раздельном построении некластеризованных индексов. Это объясняет, почему вы обнаружили, что загрузка таблиц с существующими индексами происходит быстрее (поскольку все некластеризованные индексы для данной таблицы сохраняются перед переходом к следующей таблице).
Резюме
Процесс импорта должен быть переработан так, чтобы загружать по одной таблице за раз. Это означает загрузку таблицы и построение всех некластеризованных индексов перед переходом к следующему. Экземпляр SQL Server должен иметь достаточно памяти для хранения самой большой таблицы и одновременной сортировки по наибольшему некластерному индексу.
Вы могли бы также попытаться включить TF 610 перед загрузкой данных в таблицы с некластеризованными индексами уже на месте. Обычно это не так быстро, как в предыдущем методе, но может быть достаточно быстрым.
Для получения дополнительной информации смотрите следующее:
Руководство по производительности загрузки данных
Операции, которые могут быть минимально зарегистрированы
источник