Может ли первичный ключ быть некластеризованным индексом в кластеризованной таблице?

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

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

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

Итак, могу ли я сделать некластеризованный индекс первичным ключом? Таким образом, таблица имеет как кластеризованный индекс с электронной почтой в качестве уникального ключа, так и первичный ключ int в качестве некластеризованного индекса сверху?

Спасибо, Дункан


person Duncan Gravill    schedule 09.05.2011    source источник


Ответы (3)


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

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

Я бы сделал первичный ключ IDENTITY int и кластер на нем.

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

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

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

Реальная скорость запроса (чтения) для типичных запросов OLTP достигается за счет покрытия запроса максимально узкими некластеризованными индексами для всех таблиц в запросе с каждым столбцом в соответствующем порядке и правильным направлением сортировки для запроса/параметров.

person Cade Roux    schedule 09.05.2011
comment
Электронная почта +1 кажется мне особенно плохим кластеризованным индексом - person Matthew; 09.05.2011
comment
+1 А также sqlskills.com/blogs/ Кимберли/пост/ - person gbn; 09.05.2011
comment
@gbn ссылка на sqlskills должна автоматически появляться каждый раз, когда кто-то спрашивает о кластерных индексах в SO. - person Cade Roux; 09.05.2011
comment
@Cade Roux Спасибо за ваш ответ, но я до сих пор не понимаю, почему адрес электронной почты может стать плохим ключом кластеризованного индекса. Почему он должен быть узким? Пользовательские данные по-прежнему будут почти все время просматриваться по электронной почте, независимо от того, является ли это ключом кластеризованного индекса или ключом некластеризованного индекса, поэтому в любом случае потребуются одни и те же вычисления, только если это ключ некластеризованного индекса, тогда как только пользователь будет найден в этом индексе, его нужно будет снова найти в кластеризованном индексе. В чем преимущество int PK, если доступ к данным через него осуществляется только в 5% случаев? - person Duncan Gravill; 09.05.2011
comment
@ FunkyFresh84, индекс указывает на расположение данных. В упрощенном виде кластеризованный индекс ускорит поиск последовательных строк, поскольку они физически расположены рядом друг с другом. Это не ускорит извлечение данных из single указателя. - person Matthew; 09.05.2011
comment
@ FunkyFresh84 Вы хотите, чтобы ваши некластеризованные индексы покрывали, и да, они также могут быть фрагментированы. Обычно администраторы баз данных прекрасно справляются с дефрагментацией индексов, но не с перемещением данных. Для малых n вам не нужно слишком беспокоиться об этих вещах, но когда вы доберетесь до миллионов строк, статьи Кима Триппа верны. Узкий (предпочтительно фиксированный), чтобы пространство, используемое во всех других индексах для ключа кластеризации, не было большим, увеличивающийся, чтобы уменьшить разбиение страниц, уникальный, чтобы uniquifier не добавлялся к закладкам поверх вашего ключа, статический, чтобы уменьшить разбиение страниц /фрагментация. - person Cade Roux; 09.05.2011
comment
@ FunkyFresh84 Кроме того, обратите внимание, что вы, надеюсь, собираетесь извлекать данные в одной операции SQL на основе набора, присоединяя вещи по мере необходимости к ПК, не получая ПК из электронной почты, а затем получая другие вещи из своего клиентского кода. В этих случаях внутренний суррогатный ПК может не отображаться в большинстве (возможно, ни в одном) наборе результатов. - person Cade Roux; 09.05.2011
comment
Cade Roux, Matthew PK, gbn и ck благодарят вас всех за отличную помощь. Я многому научился там за короткий промежуток времени, и прямо сейчас я прочитаю блог Кима Триппа и посмотрю на sqlskills! - person Duncan Gravill; 09.05.2011

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

Тем не менее, я утверждаю, что у вас немного наоборот. Адрес электронной почты создаст особенно ПЛОХОЙ кластеризованный индекс, потому что он изначально не упорядочен. По мере роста таблицы вы потеряете INSERT производительность из-за разделения страниц, изменения порядка и т. д.

Как сказал @Cade Roux, я бы сделал autonum кластерным индексом, обеспечил уникальность адреса электронной почты.

EDIT: кластеризованный индекс показывает, как данные физически хранятся на диске. Непоследовательные кластеризованные индексы снижают INSERT производительность, поскольку данные необходимо переупорядочивать (что приводит к разбиению страниц). При сканировании отдельных строк в таблице пользователей вы, скорее всего, обнаружите незначительную разницу между кластеризованным и некластеризованным индексом. Однако, согласно отличной ссылке, опубликованной @gbn, вы можете иметь лучшую производительность при выборе диапазона, поскольку данные являются последовательными. Тем не менее лично мне пришлось бы серьезно обдумать решение об использовании строк (или любых изначально неупорядоченных данных) для кластеризованного индекса.

EDIT2: Один исключительный случай, о котором я могу подумать, это если вы обычно выбираете группы пользователей по адресам электронной почты в алфавитном порядке... у вас все еще будут более медленные INSERT, но вы сможете получить эти группы быстрее ... Однако, как сказал @Cade Roux в комментариях: вы не должны ожидать, что однострочные SELECT будут более производительными из-за кластеризованного индекса.

person Matthew    schedule 09.05.2011
comment
Спасибо за ответ. Однако я не понимаю, как электронная почта не упорядочена по своей сути. Конечно, если бы это был ключ кластерного индекса, то поиск пользователей по электронной почте был бы похож на поиск в словаре. Может быть, вставки будут медленнее, но, конечно же, поиск будет быстрее? - person Duncan Gravill; 09.05.2011
comment
@ FunkyFresh84 кластеризованный индекс отражает то, как данные физически хранятся на диске. Это та же самая причина, по которой неупорядоченные направляющие не являются хорошими кластеризованными индексами. Скажем, пользователь создает [email protected], затем второй пользователь создает [email protected]... третий пользователь создает [email protected]... кластерный индекс должен переупорядочивать данные для выполнения вставки. Это отличается от автонумерации, где новая запись просто идет последней в кластеризованном индексе. Такое же B-дерево будет построено для индекса; нет необходимости кластеризоваться по электронной почте - person Matthew; 09.05.2011
comment
@ FunkyFresh84 Поиск будет быстрее при поиске / сканировании кластеризованного индекса, чем при сканировании таблицы, но поиск некластеризованного индекса почти всегда быстрее, потому что NCI подходит для большего количества строк на страницу. - person Cade Roux; 09.05.2011

Да, ты можешь. Когда вы создаете таблицу, установите столбцы следующим образом:

CREATE TABLE Members
(
  ID INT NOT NULL IDENTITY(10000,1),
  Email Varchar(200) NOT NULL CONSTRAINT pk_Members PRIMARY KEY NONCLUSTERED,
  Otherstuff ...
)

CREATE CLUSTERED INDEX cdx_Members ON Members(ID)
person cjk    schedule 09.05.2011
comment
Спасибо за вашу помощь, это отвечает на мой вопрос. За исключением того, что я имел в виду, что Email должен быть ключом кластеризованного индекса, а Int должен быть некластеризованным PK. У вас есть комментарии по этому поводу? - person Duncan Gravill; 09.05.2011