Использование бессмысленного идентификатора в качестве моего кластерного индекса, а не моего первичного ключа - PullRequest
2 голосов
/ 11 апреля 2011

Я работаю в SQL Server 2008 R2

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

CREATE TABLE [dbo].[Zip_Perf_by_Day] (
[CampaignID] int NOT NULL,
[ZipCode] int NOT NULL,
[ReportDate] date NOT NULL,
[PerformanceMetric1] int NOT NULL,
[PerformanceMetric2] int NOT NULL,
[PerformanceMetric3] int NOT NULL,
and so on... )

Теперь комбинация CampaignID, ZipCode и ReportDate является идеальным естественным ключом, они однозначно идентифицируют одну сущность и не должныбыть 2 записи для одной и той же комбинации значений.Кроме того, почти все мои запросы к этой таблице будут отфильтрованы по одному или нескольким из этих трех столбцов.Однако, думая о моем кластерном индексе для этой таблицы, я сталкиваюсь с проблемой.Эти 3 столбца не увеличиваются с течением времени.ReportDate в порядке, но CampaignID и Zipcode будут повсюду при вставке строк.Я даже не могу заказать их заранее, потому что результаты поступают из разных источников в течение дня, поэтому данные для CampaignID 50000 могут быть вставлены в 10:00, а CampaignID 30000 могут быть введены в 14:00.Если я использую PK в качестве кластерного индекса, я столкнусь с проблемами фрагментации.

Поэтому я подумал, что мне нужен столбец Identity ID, назовем его PerformanceID.Я не вижу ни одного случая, когда бы я использовал PerformanceID ни в списке выбора, ни в предложении где-либо из запросов.Должен ли я использовать PerformanceID в качестве моего PK и кластеризованного индекса, а затем установить уникальные ограничения и некластеризованные индексы для CampaignID, ZipCode и ReportDate?Должен ли я сохранить эти 3 столбца в качестве моего PK и просто иметь свой кластеризованный индекс PerformanceID?(<- Это вариант, к которому я сейчас склоняюсь) Можно ли иметь слегка фрагментированный стол?Есть ли другой вариант, который я не рассмотрел?Я ищу то, что дало бы мне лучшую производительность при чтении, но не полностью ухудшило бы производительность записи. </p>

Некоторая фактическая информация об использовании.Эта таблица будет записана в пакетном режиме.Ленты поступают в разное время в течение дня, обрабатываются, и эта таблица записывается.Он будет внимательно читаться, так как здесь важна повседневная производительность.Когда я заполню эту таблицу, она должна иметь около 5 миллионов строк и будет расти со скоростью около 8 000–10 000 строк в день.

Ответы [ 3 ]

3 голосов
/ 11 апреля 2011

По моему опыту, вы, вероятно, хотите использовать другое поле INT Identity в качестве ключа кластерного индекса.Я также добавил бы к этому ограничение UNIQUE (это помогает с планами выполнения).

Большая часть причины - это пространство - если вы используете ключ 3 поля для своего кластеризованного индекса, у вас будетвсе 3 поля в каждой строке каждого некластеризованного индекса в этой таблице (как идентификатор строки вашего кластеризованного индекса).Если вы планируете иметь только пару индексов, это не имеет большого значения, но если у вас их много, это может иметь большое значение.Чем больше данных в строке, тем больше нужно страниц и тем больше ввода-вывода.

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

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

Если вы хотите использовать эти три поля как FK в других таблицах, то непременно должны иметьони как ваш PK.

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

РЕДАКТИРОВАТЬ:

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

2 голосов
/ 11 апреля 2011

По представленной информации (ReportDate, CampaignID, ZipCode) или (ReportDate, ZipCode, CampaignID) кажутся лучшими кандидатами для кластеризованного индекса, чем суррогатный ключ.Дефрагментация может стать потенциальной проблемой, если время, затрачиваемое на перестроение индексов, станет непомерно высоким, но учитывая размеры, которые я ожидаю для этой таблицы (10 или 1000, а не 1 000 000 строк в день), что вряд ли является проблемой.

1 голос
/ 11 апреля 2011

Если я понял все, что вы написали правильно, вы отказываетесь от естественной кластеризации из-за штрафов за фрагментацию.

Для этой цели вы рассматриваете бессмысленные идентификаторы , которые будут:

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

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

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

С базами данных зачастую относительно легко создавать сценарии, которые будут создавать реальные тесты с реальными рабочими нагрузками и реалистичными объемами данных.

...