Разница между созданием ключей Guid в C # и БД - PullRequest
11 голосов
/ 30 января 2009

Мы используем Guids в качестве первичных ключей для сущностей в базе данных. Традиционно, мы следовали шаблону, позволяющему базе данных устанавливать идентификатор для объекта во время INSERT, я думаю, в основном потому, что, как правило, это то, как вы будете обрабатывать вещи, используя поле автоинкремента или что-то еще.

Я все больше и больше нахожу, что намного удобнее назначать ключи в коде во время конструирования объекта по двум основным причинам:

  1. вы знаете, что после запуска конструктора объекта все его поля были инициализированы. У вас никогда не будет "полуобожженных" объектов, которые бьются вокруг.
  2. если вам нужно выполнить пакет операций, некоторые из которых зависят от знания ключа объекта, вы можете выполнить их все сразу, без обращения к базе данных.

Есть ли веские причины не делать что-то таким образом? То есть, при использовании Guids в качестве ключей, есть ли веская причина оставить назначение ключей в базе данных?

Edit: Многие люди твердо придерживаются мнения о том, следует ли использовать Guides для PK (что я знал), но на самом деле это не было вопросом моего вопроса.

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

Ответы [ 9 ]

5 голосов
/ 30 января 2009

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

4 голосов
/ 30 января 2009

Делая это в C #, вы можете рискнуть переназначить GUID и сохранить его обратно в базу данных. Если база данных будет ответственна за это, вы гарантированно не измените этот PK, то есть, если вы установите соответствующие ограничения. Сказав это, вы можете установить аналогичные ограничения в своем коде C #, которые не позволяют изменять уникальный идентификатор после его назначения, но вам придется делать то же самое во всех ваших приложениях ... На мой взгляд, иметь его в C # Похоже, это больше обслуживания, чем базы данных, поскольку базы данных уже имеют встроенные методы для предотвращения изменения первичных ключей.

2 голосов
/ 31 января 2009

Интересный вопрос.

Традиционно я тоже использовал назначенный guid для БД, но недавно я работал над приложением для Windows Mobile, а база данных SQL CE не поддерживает newguid, поэтому мне пришлось делать это в коде.

Я использую репликацию SQL для передачи данных с мобильных устройств на сервер. За последние 6 месяцев у меня было 40 клиентов SQL CE, которые синхронизировали более 100000 записей с сервером SQL 2005 без одного пропущенного или дублированного руководства.

Требуемое дополнительное кодирование было пренебрежимо мало, а преимущество знания guid перед вставкой фактически сократило некоторые сложности.

Я не проводил никаких проверок производительности, поэтому помимо производительности я не вижу причин, чтобы не реализовывать обработку guid, как вы предлагаете.

1 голос
/ 31 января 2009

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

1 голос
/ 30 января 2009

GUID ужасны для производительности

Я бы оставил это в базе данных, особенно теперь, когда SQL Server имеет NEWSEQUENTIALID () , который больше не вызывает разбиения страницы на вставках, поскольку значения случайны, каждый созданный NEWSEQUENTIALID будет больше, чем предыдущий one ... only caviat в том, что его можно использовать только как значение по умолчанию

0 голосов
/ 31 января 2009

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

GUID, так как индексы всегда будут ужасно загромождены - для этого нет «правильной» настройки (если вы не используете функцию NEWSEQUENTIALGUID в механизме SQL Server).

Самым большим недостатком IMHO является размер - GUID равен 16 байтам, INT равен 4. PK хранится не только в дереве первичного ключа, но также и в КАЖДОЙ записи некластеризованного индекса.

С несколькими тысячами записей это может не иметь большого значения - но если у вас есть таблица с миллионами или миллиардами записей и несколькими некластеризованными индексами, то используйте 16-байтовый GUID против 4-байтового INT в качестве PK может иметь ОГРОМНОЕ различие в необходимом пространстве - на диске и в ОЗУ.

Марк

0 голосов
/ 31 января 2009

Хорошо, настало время подключиться. Я бы сказал, что сгенерированные GUID на стороне клиента для сохранения в базе данных - это лучший способ сделать что-то - при условии, что вы используете GUID в качестве своих PK, что я рекомендую только в одном сценарий: отключенная среда.

Когда вы используете отключенную модель для распространения данных (например, приложения для КПК / мобильных телефонов, приложения для ноутбуков, предназначенные для сценариев с ограниченными возможностями подключения и т. Д.), Лучшим способом сделать это являются GUID, создаваемые PK на стороне клиента.

Для любого другого сценария вам, вероятно, лучше использовать автоматические инкрементные идентификаторы PK.

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

0 голосов
/ 31 января 2009

Как отметил SQLMenace, стандартные идентификаторы GUID негативно влияют на индексирование и подкачку страниц. В C # вы можете генерировать последовательные идентификаторы GUID, такие как NEWSEQUENTIALID (), используя небольшую забаву P / Invoke.

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

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

0 голосов
/ 30 января 2009

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

...