Несколько столбцов " ID " в базе данных SQL Server?

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

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

обновление

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

Я думал, что Guid будет PK и использовать его для построения всех отношений / соединений и т. д. Тогда я бы вместо использования естественного ключа для индекса кластера добавил дополнительный "ID", который не зависит от данных. Мне интересно, это плохо?

8 ответов


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

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


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

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


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

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


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

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

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

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

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


плохо ли вставлять дополнительный искусственный " id " для кластеризации, так как я не уверен, что у меня будет хороший естественный ID-кандидат для кластеризации?

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


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

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

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


пример:

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

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

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

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

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


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


лично я бы поехал так:

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

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


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

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

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


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

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

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