SQL Server 2008 - Секционирование и кластерные индексы

16

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

Комментарии о том, как мы должны переосмыслить аспекты дизайна, скорее всего правильные, но бесполезные :)

У меня очень большая таблица, около 150 полей в ширину и около 600 м строк, которая управляет большим количеством процессов. Это в ситуации с хранилищем данных, поэтому у нас нет ЛЮБЫХ обновлений / вставок вне запланированного процесса загрузки, поэтому он сильно проиндексирован.

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

В настоящее время мы группируем поле, которое мы будем называть, IncidentKeyкоторое является varchar(50)уникальным и может иметь от 1 до 100 записей IK(без комментариев, пожалуйста). Мы часто получаем новые данные о старых IncidentKeyзаписях, поэтому они также не являются последовательными.

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

Вопрос в том, как будет работать механизм кластерного индекса для ключа из 2 частей в многораздельной таблице, если запись в «новом» разделе должна быть перед записью в «старом» разделе в кластерном индексе?

Например, у меня есть 5 записей:

IncidentKey    Date

ABC123        1/1/2010
ABC123        7/1/2010
ABC123        1/1/2011
XYZ999        1/1/2010
XYZ999        7/1/2010

Если я получу новую запись для ABC123, 2/1/2011него, необходимо будет в кластеризованном индексе ДО XYZ999, 1/1/2010 . Как это работает?

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

JNK
источник
Почему было принято решение разделить таблицу? Каковы ожидаемые выгоды от разделения?
Ремус Русану
@Remus - на самом деле я делаю это в качестве теста, поэтому у нас будет одна разделенная и одна неразделенная версия. Ожидаемое преимущество заключается в уменьшении времени загрузки и времени создания индекса. Мы проводим ежемесячные операции ETL, которые занимают около недели, и мы надеемся, что это значительно сократит это время. У нас также есть развертывание около 3 ТБ, которое мы надеемся сократить с этим.
JNK

Ответы:

18

Разделенная таблица действительно больше похожа на набор отдельных таблиц, соединенных вместе. Например, в примере кластеризации IncidentKeyи секционирования IncidentDate, скажем, что функция секционирования разбивает таблицы на два раздела, так что 1 января 2010 года находится в разделе 1, а 1 июля 2010 года - во втором разделе. Данные будут выложены на диск как:

Partition 1:
IncidentKey    Date
ABC123        1/1/2010
ABC123        1/1/2011
XYZ999        1/1/2010

Partition 2:
IncidentKey    Date
ABC123        7/1/2010
XYZ999        7/1/2010

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

Любая строка в любом некластеризованном индексе будет иметь ключ кластерного индекса, которому он соответствует, скажем ABC123,7/1/2010. Поскольку ключ кластеризованного индекса всегда содержит столбец ключа секционирования, подсистема всегда будет знать, в каком разделе (наборе строк) кластерного индекса искать это значение (в данном случае в разделе 2).

Теперь, когда вы имеете дело с секционированием, вы должны учитывать, будут ли ваши индексы NC выровнены (индекс NC разделен точно так же, как кластеризованный индекс) или не выровнены (индекс NC не секционирован или разделен не так, как кластерный индекс) , Несогласованные индексы более гибкие, но у них есть некоторые недостатки:

  • для невыровненных индексов требуются большие объемы памяти для определенных планов запросов
  • невыровненные индексы препятствуют эффективным операциям переключения разделов

Использование выровненных индексов решает эти проблемы, но порождает собственный набор проблем, потому что этот физический вариант хранилища влияет на модель данных:

  • выровненные индексы означают, что уникальные ограничения больше не могут быть созданы / применены (кроме столбца разделения)
  • все внешние ключи, ссылающиеся на многораздельную таблицу, должны включать в отношение ключ разделения (так как ключ разделения из-за выравнивания присутствует в каждом индексе), и это, в свою очередь, требует, чтобы все таблицы, ссылающиеся на таблицу разделения, содержали значение столбца ключа разделения. Подумайте Orders-> OrderDetails, если у Order есть OrderID, но он разделен на OrderDate, тогда OrderDetails должен содержать не только OrderID, но и OrderDate, чтобы правильно объявить ограничение внешнего ключа.

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

Если вы думаете, что выровненные индексы - это редкий или экстремальный случай, то подумайте об этом: во многих случаях краеугольным камнем решений ETL и секционирования является быстрое переключение промежуточных таблиц. Операции переключения требуют выровненных индексов.

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

Ремус Русану
источник
Отлично, это именно то, что я искал. Нам нужно будет использовать выровненные индексы, поскольку обмен является частью розыгрыша того, что мы хотим сделать с этим. Мы также выполняем ТОННУ агрегатных функций, группирующихся в этой IncidentKeyобласти, что, я думаю, серьезно помешает. Я ценю все детали!
JNK
Обычно преимущества операций переключения разделов перевешивают все проблемы.
Ремус Русану
Это наша надежда, мы скоро увидим!
JNK
9

Когда кластеризованный индекс имеет несколько разделов, каждый раздел имеет структуру B-дерева, которая содержит данные для этого конкретного раздела. Например, если кластерный индекс имеет четыре раздела, существует четыре структуры B-дерева; по одному в каждом разделе. СсылкаСтруктуры кластерного индекса

Специальные рекомендации для секционированных индексов

Вы можете перестроить определенные разделы многораздельного индекса.

например

ALTER INDEX IX_TransactionHistory_TransactionDate
ON Production.TransactionHistory
REBUILD Partition = 5;
GO
Митч Пшеничный
источник
+1 Для ссылки я прочитал специальные инструкции, но пропустил этот абзац. Дополнительный вопрос - мы проводим большую агрегацию на IncidentKeyместах, как вы думаете, это отрицательно скажется на производительности (я понимаю, что мне все еще нужно будет проводить тестирование)?
JNK
Я не знаю всех ваших конкретных обстоятельств, но мне кажется, что вам лучше разделить по IncidentDate?
Митч Пшеничный
Мы делим на дату, но кластерный ключ включен IncidentKey- мы делаем кучу объединений по этому, и это своего рода институциональная вещь, которую мы используем это для кластеризации. Я тестирую альтернативный ключ, но сейчас это то, что я должен использовать.
JNK