Имеет ли значение порядок столбцов в индексе PK?
Да, это так.
По умолчанию ограничение первичного ключа применяется в SQL Server с помощью уникального кластеризованного индекса. Кластерный индекс определяет логический порядок строк в таблице. Может быть добавлено несколько дополнительных страниц индекса для представления верхних уровней индекса b-дерева, но самый низкий (конечный) уровень кластеризованного индекса - это просто логический порядок самих данных.
Чтобы было ясно, строки на странице не обязательно физически хранятся в порядке ключей кластерного индекса. На странице есть отдельная структура косвенного обращения, в которой хранится указатель на каждую строку. Эта структура отсортирована по ключам кластерного индекса. Кроме того, каждая страница имеет указатель на предыдущую и следующую страницу на одном уровне в порядке ключей кластеризованного индекса.
При кластеризованном первичном ключе (RowNumber, DataDate)
строки сначала логически сортируются, RowNumber
а затем DataDate
- так, чтобы все строки RowNumber = 1
были логически сгруппированы, а затем строки RowNumber = 2
и так далее.
Когда вы добавляете новые данные (с RowNumbers
1 по n), новые строки логически принадлежат существующим страницам, поэтому SQL Server, скорее всего, придется много работать, разбивая страницы, чтобы освободить место. Вся эта деятельность генерирует много дополнительной работы (включая регистрацию изменений) без какой-либо выгоды.
Разделение страниц также начинается примерно на 50% пустым, поэтому чрезмерное разделение также может привести к низкой плотности страниц (меньше строк, чем оптимально для каждой страницы). Это не только плохие новости для чтения с диска (более низкая плотность = больше страниц для чтения), но страницы с более низкой плотностью также занимают больше места в памяти при кэшировании.
Изменение кластеризованного индекса на (DataDate, RowNumber
) означает, что новые данные (предположительно, выше, DataDates
чем хранящиеся в настоящее время) добавляются к логическому концу кластеризованного индекса на свежих страницах. Это удалит ненужные накладные расходы на разделение страниц и приведет к ускорению загрузки. Менее фрагментированные данные также означают, что операция упреждающего чтения (чтение страниц с диска непосредственно перед тем, как они необходимы для текущего запроса) может быть более эффективной.
Если ничего другого, ваши запросы будут искать чаще, DataDate
чем RowNumber
. Кластерный индекс включен (DataDate, RowNumber
) поддерживает поиск индекса DataDate
(и затем RowNumber
). Существующая договоренность поддерживает только поиск RowNumber
(и только тогда, возможно, включение DataDate
). Возможно, вы сможете удалить существующий некластеризованный индекс DataDate
после изменения первичного ключа. Кластерный индекс будет шире, чем некластеризованный индекс, который он заменяет, поэтому вам следует проверить, чтобы производительность оставалась приемлемой.
При импорте новых данных с bcp
, вы можете получить более высокую производительность, если данные в файле импорта сортируются по ключам кластеризованного индекса (в идеале (DataDate, RowNumber
)), и вы указываете bcp
опцию:
-h "ORDER(DataDate,RowNumber), TABLOCK"
Для достижения максимальной производительности при загрузке данных вы можете попытаться использовать минимально вставленные записи. Для получения дополнительной информации см .: