Стоит ли добавлять INT к таблице, для которой PRIMARY KEY является УНИКАЛЬНЫМ РАЗРЕШИТЕЛЕМ для целей таблицы JOIN? - PullRequest
0 голосов
/ 01 августа 2011

В моей базе данных SQL Server 2008 есть две таблицы: Пользователи и элементы

tblUser 
--------------------------
UserID    uniqueidentifier
Name      nvarchar(50)
etc..


tblItem 
--------------------------
ItemID    uniqueidentifier
ItemName      nvarchar(50)
etc..

tlmUserUserItem
----------------------------
ItemID      uniqueidentifier
UserID_A    uniqueidentifier
UserID_B    uniqueidentifier

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

Таблица соединения должна быть проиндексирована по столбцам UserID_A и UserID_B, так как поиски основаны на пользователях по отношению к своим партнерам.

Мой вопрос такой:

Стоит ли добавлять в пользовательскую таблицу значение автоинкремента INT для использования в качестве не первичного ключа, а затем использовать его в таблице соединений? Таким образом, таблица User выглядит так:

tblUser 
---------------------------------
UserID         uniqueidentifier
Name           nvarchar(50)
UserIDJoinKey  int  identity(1,1)
etc..

Делая это, будет быстрее сделать что-то вроде:

declare @ID int
select * from tblJoin where UserIDJoinKey_A = @ID or UserIDJoinKey_B = @ID

когда таблица соединения выглядит следующим образом:

tlmUserUserItem
-----------------------------------
ItemID             uniqueidentifier
UserIDJoinKey_A    int
UserIDJoinKey_B    int

вместо этого:

tlmUserUserItem
----------------------------
ItemID      uniqueidentifier
UserID_A    uniqueidentifier
UserID_B    uniqueidentifier

Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 31 августа 2011

Если у вас проблемы с производительностью при операциях соединения с таблицей с помощью uniqueidentifier, сначала проверьте фрагментацию индекса.Горячие таблицы с кластеризованным индексом uniqueidentifier имеют тенденцию быстро фрагментироваться.Хорошую информацию о том, как это сделать, можно узнать по http://msdn.microsoft.com/en-us/library/ms189858.aspx

. Если вы можете переместить кластерный индекс в новый столбец int и переписать свои запросы, чтобы использовать новый столбец int вместо старого uniqueidentifier, вы 'Самое большое преимущество будет в том, что вы уменьшите скорость фрагментации.Это помогает избежать замедления ваших запросов после нескольких записей в таблицу.

В большинстве случаев вы не заметите огромной разницы во времени обработки операций соединения в столбце uniqueidentifier по сравнению с int в MSSQL.2008 - при условии, что все остальные вещи (включая фрагментацию) равны.

1 голос
/ 31 августа 2011

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

Если нет конкретной причины, по которой вам нужно было использовать указатель над идентификатором, я быСкажи ломать GUID все вместе.Это раздувает ваши таблицы, индексы и замедляет ваши объединения.Если я неправильно понимаю, пожалуйста, дайте мне знать, и я прошу прощения!

0 голосов
/ 26 апреля 2012

@ MikeM

Лично я бы всегда выбирал uniqueidentifier вместо int в качестве первичного ключа таблицы каждый раз. Однако я бы использовал NEWSEQUENTIALID (), а не NEWGUID (), чтобы обеспечить меньшую фрагментацию индекса.

Причина, по которой я делаю этот выбор, проста:

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

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

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

0 голосов
/ 01 августа 2011

Чтобы узнать, что является лучшим решением, сначала рассмотрим теорию индексации.SQL Server хранит данные своего кластерного индекса в дереве B + страниц данных, которое допускает около 8K данных на страницу.Если вы знаете, что uniqueidentifier составляет 16 байт на ключ, а int - 4 байта на ключ, это означает, что на индексную страницу будет в 4 раза больше ключей с int.

Чтобы иметь более быстрое объединение со столбцом int, вам, скорее всего, придется сделать его кластеризованным индексом.Имейте в виду, что наличие дополнительного индекса для такой большой таблицы может привести к нежелательному падению производительности операторов вставки, поскольку существует больше информации для записи на диск.

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

...