Что лучше: сначала внести данные в таблицу, а потом создать индекс, или наоборот
Что проверяют
Понимаете ли вы, как физически строится индекс, и отличаете ли разовую загрузку от дозаливки в живую таблицу. Ответ «сначала данные» верен не всегда, и интереснее всего, назовёте ли вы исключение.
Как отвечать
Для разовой загрузки в пустую таблицу: сначала данные, потом индексы. Причина в механике. Вставка в существующий индекс это попадание в случайную страницу, расщепления страниц и запись в журнал на каждую строку, а построение индекса после загрузки это одна сортировка и последовательное заполнение страниц.
Дальше оговорки, которые отличают понимание от заученного правила:
- кластерный индекс в SQL Server это и есть сама таблица. Залить в кучу, а потом построить кластерный индекс означает переписать все данные целиком, поэтому его часто выгоднее создать заранее и подавать строки в порядке ключа;
SqlBulkCopyс блокировкой таблицы и разумным размером пакета при подходящей модели восстановления даёт минимальное логирование, и это влияет на время сильнее, чем игры с индексами;- уникальные ограничения и внешние ключи снимать опаснее: дубликаты тогда всплывут только при создании индекса, то есть в конце многочасовой загрузки;
- в работающую таблицу с читателями индексы не снимают вовсе, это ломает планы запросов, а перестроение обойдётся дороже самой вставки.
Где спотыкаются
Отключают кластерный индекс заодно с некластерными. У таблицы с отключённым кластерным индексом данные становятся недоступны, и загрузка падает на первой же операции.
Второе: переносят результат лабораторного замера на промышленную базу. На пустой таблице выигрывает один порядок действий, на таблице с миллиардом строк, конкурентными запросами и репликацией совсем другой.
Третье: забывают про статистику и журнал после заливки. Планы продолжают строиться по устаревшей статистике, а журнал транзакций, раздутый одной гигантской транзакцией, никто потом не разбирает.