Несколько столбцов «ID» в базе данных SQL Server? - PullRequest
6 голосов
/ 14 января 2010

Через эту ссылку, я знаю, что GUID не годится в качестве кластерного индекса, но он может быть уникально создан где угодно. Это требуется для некоторых расширенных функций SQL Server, таких как репликация и т. Д.

Считается ли это плохим дизайном, если я хочу иметь столбец GUID в качестве типичного первичного ключа? Также это предполагает наличие отдельного столбца int для моего идентификатора кластеризации, а в качестве дополнительного бонуса - «удобный для пользователя» идентификатор?

обновление

После просмотра вашего отзыва я понимаю, что не правильно сформулировал свой вопрос. Я понимаю, что Guid делает хороший (даже если его избыточный) PK, но плохой индекс кластеризации (в целом). Мой вопрос более прямо задан: плохо ли добавлять второй столбец «int identity» в качестве индекса кластеризации?

Я думал, что Guid будет PK и будет использовать его для построения всех связей / объединений и т. Д. Тогда вместо использования естественного ключа для индекса кластера я бы добавил дополнительный «идентификатор», который не конкретный. Что мне интересно, это плохо?

Ответы [ 8 ]

2 голосов
/ 14 января 2010

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

Используйте GUID, если нужно для репликации, но не используйте его в качестве первичного ключа.

1 голос
/ 14 января 2010

Рассмотрите возможность использования только GUID, но получите свои GUID, используя метод NEWSEQUENTIALID (который назначает последовательные значения и поэтому не имеет тех же проблем производительности кластеризации, что и NEWID метод).

Проблема с использованием вторичного ключа INT в качестве индекса заключается в том, что, если это адекватный индекс, зачем вообще использовать GUID? Если GUID необходим, как вы можете использовать вместо этого индекс INT? Я не уверен, нужен ли вам GUID, и если да, то почему: вы делаете репликацию и / или объединяете несколько баз данных? И если вам действительно нужен GUID, то вы не указали точно, как вы собираетесь использовать не глобально уникальный индекс INT в этом сценарии.


Звучит так, будто вы говорите, что я вообще не привел достаточных оснований для использования Guid, и я согласен, что знаю его излишество, но я думаю, что мой вопрос - слишком ли это слишком много?

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

Больше всего беспокоит то, как использование (случайного) GUID может повлиять на производительность, когда он используется для кластеризации. Для противодействия этому:

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

  • Или, пусть кластеризованный индекс будет тем же полем, что и первичный ключ GUID, но используйте NewSequentialId () вместо NewId () для выделения значений GUID.


Разве плохо вставлять дополнительный искусственный «идентификатор» для кластеризации, поскольку я не уверен, что у меня будет хороший естественный идентификатор кандидата для кластеризации?

Я не понимаю, почему вы не хотели бы вместо этого использовать только GUID с NewSequentialId (), который, я думаю, предоставляется именно по этой причине.

1 голос
/ 14 января 2010

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

Если вам нравятся "красивые" идентификаторы, сгенерированные с использованием шаблона Active Record, то я думаю, что я бы попробовал использовать его вместо GUID. Если вам нужна репликация, используйте одну из стратегий репликации, подходящую для столбцов идентификации.

1 голос
/ 14 января 2010

Использование GUID лениво - то есть, администратор БД не может быть обеспокоен тем, чтобы правильно моделировать свои данные. Также он предлагает очень плохую производительность соединения - обычно (16-байтовый тип с плохой локальностью).

Это плохой дизайн, если я хочу иметь столбец GUID в качестве моего типичного первичного ключа и отдельный столбец int для моего идентификатора кластеризации, а в качестве дополнительного бонуса - «удобный для пользователя» идентификатор?

Да, это очень плохо - во-первых, вам не нужно более одного «искусственного» ключа-кандидата для вашей таблицы. Во-вторых, если вы хотите, чтобы в качестве ключей использовался удобный идентификатор, просто используйте тип фиксированной длины, такой как char [8] или binary (8) - предпочтительно двоичный, так как сортировка не будет использовать локаль; вы можете использовать 16-байтовые типы, однако вы заметите ухудшение производительности, но не так плохо, как GUID. Вы можете использовать эти фиксированные типы для создания собственной удобной схемы размещения, которая сохраняет некоторую локальность, но генерирует разумные и значимые идентификаторы.


В качестве примера:

Если вы пишете какую-то систему CRM (скажем, онлайн-котировки) и вам нужен чрезвычайно удобный для пользователя тип, например, ссылка на страховую цитату (QR), которая выглядит так: «AD CAR MT 122299432».

В этом случае - поскольку длина кавычки огромна - я бы создал отдельную LUT / Symboltable для разрешения ссылки на кавычку на фактический используемый идентификатор. но я отделю это LUT от остальной части модели, я никогда не буду использовать ссылку на цитату где-либо еще в модели, особенно в таблице, представляющей QR .

Create Table QRLut
{
    bigint bigint_id;
    char(32) QR;
}

Теперь, если в моей модели есть одна таблица, представляющая QR, и 20 других таблиц, в которых bigint QR используется в качестве внешнего ключа - тот факт, что используется bigint, позволит моей БД масштабироваться лучше - чем шире предикаты объединения, тем шире на шине памяти возникает больше конфликтов - и количество конфликтов на шине памяти определяет, насколько хорошо ваш ЦП может быть насыщен (несколько ЦП).

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

0 голосов
/ 15 января 2010

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

GUID имеют те же характеристики для кластерных индексов, что и столбцы INT IDENTITY, при условии, что GUID являются последовательными. Существует NewSequentialID, специфичный для SQL Server, но также существует универсальный алгоритм их создания, называемый COMID GUID, который основан на объединении текущей даты и времени со случайными байтами таким образом, который сохраняет большую степень случайности при сохранении последовательности.

Одна вещь, которую нужно иметь в виду, если вы собираетесь использовать NHibernate в какой-то момент, это то, что NHibernate изначально знает, как использовать стратегию COMB GUID - и NHibernate может даже использовать ее для пакетной вставки, чего нельзя с INT IDENTITY или NewSequentialID. Если вы вставляете несколько объектов с помощью NHibernate, то использовать стратегию COMB GUID будет быстрее, чем любой из двух других методов.

0 голосов
/ 14 января 2010

Лично я бы пошел по этому пути:

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

Теперь, что касается кластеризованного индекса, с которым вы можете или не можете запутаться, рассмотрите это руководство от MS для SQL Server 2000 .

0 голосов
/ 14 января 2010

Я думаю, это плохой дизайн, но я не знаю, плохо ли это в противном случае. Помните, что SQLServer автоматически назначает кластерный индекс первичному ключу. Вам придется удалить его после того, как GUID станет первичным ключом. Кроме того, вы обычно хотите, чтобы ваш столбец идентификации был вашим основным ключом. То, что вы говорите, может сбить с толку любого, кто читает ваш код, который не присматривается. Я бы посоветовал вам сделать столбец ID вашим первичным ключом, столбцом идентификаторов и поместить в него кластерный индекс. Затем сделайте свой столбец GUID уникальным ключом, сделав его некластеризованным индексом и не допустив пустых значений. Это влияет на то, что вы хотите, но будет следовать больше стандарта.

0 голосов
/ 14 января 2010

Это совсем не плохой дизайн, int Identity для вашего ключа кластеризации дает вам ряд полезных преимуществ (Narrow, Unique, Ascending), сохраняя GUID для функциональных целей очень отдельным и выступая в качестве основного ключа. *

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

Приложение: Я должен поместить в обязательную ссылку (возможно?) Наиболее читаемую статью на эту тему Кимберли Триппа. http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...