Использование кластерных индексов для столбцов, отличных от первичного ключа, при использовании оператора IN vs =

Если в моей таблице Product есть столбец CategoryId, я понимаю, что может быть хорошей практикой сделать CategoryId кластеризованным индексом, а не первичным ключом ProductId.

Это все еще применимо, если большинство моих запросов к таблице Product выглядят как select * from Product where CategoryId in (1, 2) вместо более типичного select * from Product where CategoryId = 1


person kenwarner    schedule 07.02.2012    source источник


Ответы (1)


Пожалуйста, очень внимательно выбирайте свой кластеризованный индекс! Он очень особенный - в каждой таблице может быть только один, и он определяет физический порядок данных, и он используется для уникальной идентификации местоположения ваших страниц данных ("указатель строки", если хотите).

Кроме того, это наиболее реплицируемая структура данных в вашей базе данных SQL Server (при условии, что вы говорите о SQL Server). Ключ кластеризации также будет частью каждого некластеризованного индекса в вашей таблице — конечно, на уровне листа, возможно, также в структуре навигации по индексу.

Вы должны быть предельно осторожны при выборе ключа кластеризации — он должен быть:

  • узкий (идеально 4 байта)

  • уникальный (в конце концов, это «указатель строки» — если вы не сделаете его уникальным, SQL Server — для вас — в фоновом режиме — будет стоить вам пару байтов для каждой записи — умноженное на количество строк и количество некластеризованных индексов у вас может быть очень дорого!)

  • статический (никогда не меняйте, если это возможно)

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

  • он должен быть необнуляемым и в идеале также должен быть исправлен с помощью - varchar(250) делает очень плохой ключ кластеризации

Все остальное действительно должно быть вторым и третьим уровнем важности за этими пунктами....

Ознакомьтесь с некоторыми сообщениями в блоге Кимберли Трипп (Королева индексирования) на эту тему. Все, что она написала в своем блоге, абсолютно бесценно — читайте, осмысливайте — живите этим!

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

Кроме того, похоже, что категория продукта не будет очень избирательной, поэтому она может даже не стать хорошим некластеризованным индексом. Если конкретный запрос возвращает более 1-5% от общего числа строк, большинство индексов все равно не будут использоваться оптимизатором запросов SQL (поскольку они возвращают слишком много данных).

person marc_s    schedule 07.02.2012
comment
Я впервые читаю этот вопрос, но клянусь, я где-то читал точно такой же ответ. Вы просто копируете и вставляете свои ответы? РЖУ НЕ МОГУ. - person sam yi; 07.02.2012
comment
отличный ответ и статьи, спасибо. кластеризация уникального ключа очень неинтуитивна - мне придется прочитать их еще несколько раз. - person kenwarner; 07.02.2012
comment
CategoryId в таблице Products не очень хорошая идея... скорее всего, он не уникален - я предполагаю, что они имели в виду кластеризованный индекс для соединения (CategoryId, ProductId) в таком порядке, идея в том, что при поиске только по CategoryId результаты в основном будут на одних и тех же физических страницах. - person onedaywhen; 07.02.2012
comment
@onedaywhen: это соединение на (CategoryId, ProductId) было бы гораздо лучшим выбором, да! - person marc_s; 07.02.2012