Может ли первичный ключ быть некластеризованным индексом в кластеризованной таблице? - PullRequest
0 голосов
/ 09 мая 2011

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

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

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

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

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

Ответы [ 3 ]

4 голосов
/ 09 мая 2011

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

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

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

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

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

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

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

3 голосов
/ 09 мая 2011

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

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

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

РЕДАКТИРОВАТЬ: Кластерный индекс представляет, как данные физически хранятся на диске.Непоследовательные кластеризованные индексы повлияют на производительность INSERT, так как данные должны быть переупорядочены (что приведет к расщеплению страниц).Для сканирования отдельных строк в таблице пользователей вы, вероятно, найдете незначительную разницу между кластеризованным и некластеризованным индексом.Однако, благодаря превосходной ссылке, размещенной @gbn, вы могли бы иметь лучшую производительность при выборе диапазона, потому что данные последовательны.Тем не менее, мне лично пришлось бы по-настоящему задуматься над решением использовать строки (или любые неупорядоченные данные) для кластеризованного индекса.

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

2 голосов
/ 09 мая 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)
...