Использование GUID в качестве первичного ключа

Я вообще использовать авто инкремент идентификаторов в качестве первичных ключей в базах данных. Я пытаюсь узнать преимущества использования идентификаторов GUID. Я прочитал эту статью: https://betterexplained.com/articles/the-quick-guide-to-guids/

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

public class Person
{
public GUID ID;
public string Name;
..

//Person Methods follow
}

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

Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);

Скажем, у меня есть база данных, содержащая миллионы и миллионы строк с GUID в качестве первичного ключа. Будет ли это всегда быть уникальным? Я вообще правильно понимаю идентификаторы GUID?

Я читал эту статью раньше: http://enterprisecraftsmanship.com/2014/11/15/cqs-with-database-generated-ids/. Это меня смущает немного, как это, кажется, рекомендуют золотую середину между GUID и целые числа в качестве первичных ключей.

Редактировать 11/06/18

Я пришел к выводу, что GUID являются более подходящими, чем Ints для моих требований. Я использование CQRS больше в эти дни и GUID вписываются в более красиво.

Я обратил внимание, что некоторые разработчики модели идентификаторов GUID в качестве строк в модели предметной области, например, здесь: https://github.com/dotnet-architecture/eShopOnContainers/blob/dev/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs - в данном случае: IdentityGuid-это GUID, по образцу, как струна. Есть какие-то причины для этого другие, чем то, что указано здесь: https://softwareengineering.stackexchange.com/questions/239220/use-a-custom-value-object-or-a-guid-as-an-entity-identifier-in-a-distributed-sys. Это ее "нормальный" на модели идентификатор GUID в виде строки или я должен быть его моделирования как GUID в модель и базу данных?

Комментарии к вопросу (9)

GUID являются по определению "и глобальные уникальные идентификаторы и". Там'ы есть похожие, но немного разные понятия в Java называется UUID-Ы "и универсально уникальных идентификаторов и". Имена являются взаимозаменяемыми для всех практического использования.

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

Некоторые про-идентификатор факты:

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

Какое-то безобразие с GUID

  • Они большие, 16 байт каждый
  • Они вышли из строя, так что вы можете'т Сортировать по ID и надеемся получить заявки на размещение можно как на автоинкрементные идентификаторы
  • Они являются более громоздкими, чтобы работать с, особенно на небольших наборах данных (например, таблиц)
  • Новая реализация GUID является более надежной на SQL Server, чем это в C# библиотеки (вы можете иметь последовательные идентификаторы GUID для SQL сервера, в C# это случайно)

GUID будут сделать ваши показатели больше, поэтому дисковое пространство стоимость индексирование столбца будет выше. Случайный GUID будут фрагмент индексов.

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

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

Комментарии (23)

это всегда быть уникальным?

Always? нет, не всегда; это'ы конечной последовательности битов.

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

Миллионы и миллионы, вы, вероятно, безопасны. Миллион миллионов, и вероятность столкновения]1 становится значительным. Там'хорошая новость, хотя: вы'ве уже кончились дискового пространства по времени, что происходит.

Я могу просто сделать это?

Вы можете; это's не совсем хорошая идея. Модель домена должен'т, как правило, быть генерация случайных чисел; они должны быть входы к вашей модели.

Кроме того, когда вы имеете дело с ненадежной сети, где можно получить дубликат сообщения, deterministically сгенерированный идентификатор UUID будет защищать вас от необходимости дублировать лиц. Но если вы назначите новое случайное число для каждого, тогда у вас есть больше работы, чтобы сделать, чтобы выявить дублирование.

Смотрите описание имени UUID в документе RFC 4122

> есть ее "нормальный" на модели идентификатор GUID в виде строки или я должен быть его моделирования как GUID в модель и базу данных?

Я не'т думаю, что это очень важно. Для большинства вашей модели предметной области, это identifier; единственный запрос, вы спросите его, является ли она такой же, как и некоторые другие идентификаторы. Модель домена выиграл'т, как правило, быть глядя на в памяти представление идентификатора.

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

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

Комментарии (8)

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

Преимущества идентификаторы GUID в качестве первичного ключа:

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

В примере вы указали:

Person p1 = new Person();
p1.ID = GUID.NewGUID();
PersonRepository.Insert(p1);

Указывая GUID до времени установки можно сохранить обратно в базу данных при вставке последующих детей записи и позволяют совершать их в одной транзакции.

Person p2 = new Person();
p2.ParentID = p1.ID
PersonRepository.Insert(p2);

Вредно для идентификаторов GUID в качестве первичного ключа:

  • Они большие 16 байт, то есть они потребляют больше пространства, так как индексы и внешние ключи добавляются.
  • Они не этакие же, как они, по сути, являются случайными числами.
  • Использование индекса очень, очень, очень плохо.
  • Много листьев движется.
  • Их трудно запомнить.
  • Их трудно вербализовать.
  • Они могут сделать URL-адреса'ы трудно читать.

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

Многие базы данных имеют свои собственные внутренние реализации, которые пытаются смягчить хранения проблемы, вызванные идентификатор GUID'ы и SQL Server, даже есть функция функция newsequentialid, чтобы помочь с Заказ по UUID'ы для лучшего использования индексов и они, как правило, имеют лучшие ТТХ.

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

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

Комментарии (11)
Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);

Это, безусловно, самая важная причина для использования идентификаторов GUID.

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

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

Вы можете вставить его в любом виде РБД базы данных или нет-sql, файл, отправить его на любой веб-сервис или выбрасывай его сразу, как uneeded

Нет вы никогда не будете столкновение.

Да вставки могут быть немного медленнее, так как индекс может потребоваться повертела.

Да это больше, чем int.

  • редактирование. пришлось отстрелить до окончания.

Я знаю, что многие люди убеждены о авто Инк ИНЦ и это спорная тема с администраторов баз данных

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

авто Инк ИНЦ имеют много недостатков

  • Вы используете не-SQL и распределенных БД. Вы просто не можете говорить на всех других случаях, чтобы выяснить, что следующее число.

  • Вам использовать системную очередь сообщений. Вещи нужны идентификаторы, прежде чем они попали в БД

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

  • Вы хотите удалить и повторно вставить строки. Убедитесь, что вы Дон'т прикинь вашего авто Инк идентификаторы и закончатся!

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

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

  • Вы хотите объединить один продукт арендатора в арендованную базу данных, но у каждого есть порядка 56.

  • Вы создаете объекты, которые сохраняются, но эфемерное. (невыполненных заказов) опять же, не использовали все ваши ИНЦ СО всякой всячиной, которая уже не существует.

Список бесконечен, и все они реальные проблемы, которые происходят с людьми все время. в отличие от бежать вне дискового пространства, из-за чуть большего размера ФК седла

Наконец, массовые проблемы с ИНЦ является вы бежите из них!!! ок, в теории нет, есть множество. Но на практике вы делаете, потому что люди Дон'т относиться к ним как случайные числа, не имеющим смысла. они делают такие вещи, как

  • О, я не'т хотите, чтобы клиенты думают, что мы новый. старт на 10 000

  • Мне пришлось импортировать загрузки данных, так что я просто поднял семян на 1м, поэтому мы знаем, что импортируется

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

  • Я удалил и повторно импортировать все данные с новыми идентификаторами. Да даже журналы аудита.

  • используйте этот номер, который является составной ключ, а код это другое дело

Комментарии (7)

Я'd не сказать, нет, Дон'т использовать идентификаторы GUID в качестве первичных ключей. Я'м на самом деле имеем дело с такими БД сейчас, и они являются одной из основных причин проблем с производительностью.

Лишние 12 байт сложить быстро; помните, большинство ПКС будет ФКС в другие таблицы, и всего за три ФКС в таблице, теперь у вас есть 48 байт дополнительной для каждой строки. Что добавляет вверх в таблице и в индексах. Он также добавляет в дискового ввода-вывода. эти дополнительные 12 байтов должны быть прочитаны и записаны.

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

Если вам нужен какой-то уникальный идентификатор для синхронизации или что-то, добавить столбец GUID. Просто Дон'т сделать это на ПК.

Комментарии (0)

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

Что's, где вы должны остановить прямо там, и переосмыслить.

Первичный ключ базы данных не должны иметь экономический смысл. Она должна быть бессмысленной по определению.

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

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

Комментарии (2)

Всегда использовать базу данных автоматически, автоинкрементные первичные ключи(ПКС).

Зачем использовать автоинкрементные вместо GUID/UUID и?

  • Идентификатор GUID(UUID)в S не предотвращают конфликты, поскольку они не являются уникальными, и нет никакого способа, чтобы сделать их уникальными, поскольку они создаются из многочисленных источников.
  • GUID не помочь с объединением, так как они значительно увеличивают и без того трудоемкий процесс слияние с очень длинным, не целое PK и FK в Столбцах, которые принимают много времени для обработки. Помните, что для большинства ПКС, там будет как минимум 1 другой таблице с как минимум 2 клавиши одинакового размера: это'с собственного ПК и ФК вернемся к первой таблице. Все должны быть решены в слиянии.

Но как тогда обрабатывать сегменты, кластеры и т. д.?

  • Создать многостолбцовый ПКС состоит из отдельных столбцов идентификации каждого сегментов/кластеров/базы данных/что управляет он's собственное автоинкрементные ключи. Например...

3-колонки ПК для кластеризованной таблице, может быть...

 DB | SH | KEY     |
----|----|---------|
 01 | 01 | 1234567 |

Но Что Насчет...?

  • Несколько обращений к базе данных-большинство приложений не нужно однозначно идентифицировать записи, пока он'ы внесены в базу данных так, что поток/сессия/все работает только на одном одновременно. Если приложение действительно нужна эта возможность, использовать приложение, созданное временное ПК что не отправляется в базу данных. Давайте тогда на базе выразились's собственное авто-инкремент кол-во в ряду, когда он'ы вставлен. Вставки будут использовать временную ПК во время обновления и удаления будут использовать постоянный ПК назначается базой данных.

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

Общие злоупотребления первичные ключи Пкс имеют только одну цель... абсолютно однозначно идентифицировать строку в таблице. Все остальное-это слишком часто злоупотребляют.

Обнаружение Отсутствующих Записей

  • Пропущенные записи не могут быть обнаружены, глядя на ПКС. Благослови ОК, по крайней мере, пытается обеспечить качество данных. Впрочем, они и программист'отсутствие понимания того, как ключи в современных системах баз данных часто приводит их к заблуждению, что недостающее число в автоинкрементный ПК означает отсутствие данных. Это не, потому что... На производительности систем баз данных выделяют блоки номеров в 'последовательности'(партиями, диапазоны), чтобы свести к минимуму поездки в актуальном состоянии базы данных в хранилище. Размер этих последовательностей чисел часто под контролем дБА, но не может быть настраиваемый на каждой таблицы.
  • Ключевой момент состоит в... неиспользованных чисел из этих последовательностей никогда не возвращаются к базе данных, поэтому всегда есть пробелы в ПК чисел.
  • Почему там есть неиспользуемые номера, спросите вы? Потому что различные действия по обслуживанию баз данных может привести к последовательности, чтобы отказаться. Эти вещи, как перезагрузка, массовая перезагрузка таблиц, некоторые виды восстановления из резервных копий и некоторые другие операции.

Сортировка

  • Сортировка по PK-это очень подвержен ошибкам, так как большинство людей будут думать, что это списки строк в том порядке, как они были созданы и что, что соответствует времени. В основном, но не necessarilly.
  • СУБД оптимизированы для максимальной производительности и которые могут означать отсрочку вставка результатов длительных сложных операций для того, чтобы вставить короткие простые из них, то "без очереди" так сказать.
Комментарии (4)

Вроде ничего, есть свои преимущества и недостатки, чтобы делать это:

Хороший:

  1. Ваши ключи всегда имеют одинаковую длину (очень больших баз данных может иметь очень большие ключи)

  2. Уникальность-это почти гарантировано - даже если вы'вновь создавая их из отдельной системы, и/или не'т Читать последний ID из базы данных

Плохая:

  1. Как уже упоминалось много выше - более крупные индексы и хранения данных.

  2. Вы можете'т того, по ID, вы должны заказать что-то другое. Больше индексов, вероятно, менее эффективными.

  3. Они're более менее удобочитаемое. Целые числа, как правило, легче разобрать, запомнить и набрать людей. Используя идентификаторы GUID в качестве идентификаторов в предложениях where для нескольких соединяемых таблиц может сделать вашу голову таять.

Как и все, использовать их там, где это уместно, Дон'т быть догматиком – во многих ситуациях автоматическим приращением числа лучше, иногда идентификаторы GUID являются большими.

Комментарии (0)

Здесь's мой ответ на этот вопрос - решение-это на полпути дом между GUID и int значения, взяв лучшее из обеих.

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

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

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

public static class LongIdGenerator
{
    // set the start date to an appropriate value for your implementation 
    // DO NOT change this once any application that uses this functionality is live, otherwise existing Id values will lose their implied date
    private static readonly DateTime PeriodStartDate = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    private static readonly DateTime PeriodEndDate = PeriodStartDate.AddYears(100);
    private static readonly long PeriodStartTicks = PeriodStartDate.Ticks;
    private static readonly long PeriodEndTicks = PeriodEndDate.Ticks;
    private static readonly long TotalPeriodTicks = PeriodEndTicks - PeriodStartTicks;

    // ensures that generated Ids are always positve
    private const long SEQUENCE_PART_PERMUTATIONS = 0x7FFFFFFFFFFF; 

    private static readonly Random Random = new Random();

    private static readonly object Lock = new object();
    private static long _lastSequencePart;

    public static long GetNewId()
    {
        var sequencePart = GetSequenceValueForDateTime(DateTime.UtcNow);

        // extra check, just in case we manage to call GetNewId() twice before enough ticks have passed to increment the sequence 
        lock (Lock)
        {
            if (sequencePart  endDate => 0x7FFFFFFFFFFF
    // For a 100 year time period, 1 unit of the sequence corresponds to about 0.022 ms
    private static long GetSequenceValueForDateTime(DateTime dt)
    {
        var ticksFromStart = dt.ToUniversalTime().Ticks - PeriodStartTicks;
        var proportionOfPeriod = (decimal)ticksFromStart / TotalPeriodTicks;
        var result = proportionOfPeriod * SEQUENCE_PART_PERMUTATIONS;
        return (long)result;
    }

    public static DateTime GetDateTimeForId(long value)
    {
        // strip off the random part - the two lowest bytes
        var timePart = value >> 16;
        var proportionOfTotalPeriod = (decimal) timePart / SEQUENCE_PART_PERMUTATIONS;
        var ticks = (long)(proportionOfTotalPeriod * TotalPeriodTicks);
        var result = PeriodStartDate.AddTicks(ticks);
        return result;
    }
}
Комментарии (0)

Да, вы можете использовать GUID в качестве первичного ключа. Недостаток-размер и быстрого фрагментации индекса.

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

Комментарии (1)