Я вообще использовать авто инкремент идентификаторов в качестве первичных ключей в базах данных. Я пытаюсь узнать преимущества использования идентификаторов 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 в модель и базу данных?
GUID являются по определению "и глобальные уникальные идентификаторы и". Там'ы есть похожие, но немного разные понятия в Java называется UUID-Ы "и универсально уникальных идентификаторов и". Имена являются взаимозаменяемыми для всех практического использования.
Идентификаторы GUID являются центральными как Microsoft предусмотренных базе кластеризации для работы, и если вам нужно включить сведения из подключенных источников, они реально помогают избежать конфликтов данных.
Некоторые про-идентификатор факты:
Какое-то безобразие с GUID
GUID будут сделать ваши показатели больше, поэтому дисковое пространство стоимость индексирование столбца будет выше. Случайный GUID будут фрагмент индексов.
Если вы знаете, вы'т собираюсь синхронизировать данные из разных сетей, идентификаторы GUID могут нести большую нагрузку, чем они стоят.
Если у вас есть необходимость принимать данные с иногда подключенные клиенты, то они могут быть намного более надежной для предотвращения столкновений ключа не полагаться на настройки диапазонов последовательности для этих клиентов.
это всегда быть уникальным?
Always? нет, не всегда; это'ы конечной последовательности битов.
у меня есть база данных, содержащая миллионы и миллионы строк с GUID в качестве первичного ключа.
Миллионы и миллионы, вы, вероятно, безопасны. Миллион миллионов, и вероятность столкновения]1 становится значительным. Там'хорошая новость, хотя: вы'ве уже кончились дискового пространства по времени, что происходит.
Я могу просто сделать это?
Вы можете; это's не совсем хорошая идея. Модель домена должен'т, как правило, быть генерация случайных чисел; они должны быть входы к вашей модели.
Кроме того, когда вы имеете дело с ненадежной сети, где можно получить дубликат сообщения, deterministically сгенерированный идентификатор UUID будет защищать вас от необходимости дублировать лиц. Но если вы назначите новое случайное число для каждого, тогда у вас есть больше работы, чтобы сделать, чтобы выявить дублирование.
Смотрите описание имени UUID в документе RFC 4122
> есть ее "нормальный" на модели идентификатор GUID в виде строки или я должен быть его моделирования как GUID в модель и базу данных?
Я не'т думаю, что это очень важно. Для большинства вашей модели предметной области, это identifier; единственный запрос, вы спросите его, является ли она такой же, как и некоторые другие идентификаторы. Модель домена выиграл'т, как правило, быть глядя на в памяти представление идентификатора.
Если идентификатор GUID доступен как и "примитивного типа" в настройки вашего домена агностик, я хотел бы использовать его; это позволяет поддерживать контекст, чтобы выбрать соответствующие оптимизации, которые могут быть доступны.
То, что вы должны признать, однако, что представление идентификатора, как в памяти, так и во время хранения, это решение вы делаете в своей реализации, и поэтому вы должны предпринять шаги, чтобы гарантировать, что нога печать кода в сочетании с этим решением является небольшой, см. Парнас 1972.
GUID или идентификатор скорее всего уникальный, потому что, как они создаются, и они обеспечивают безопасный способ гарантировать уникальность без необходимости общаться с центральной властью.
Преимущества идентификаторы GUID в качестве первичного ключа:
В примере вы указали:
Person p1 = new Person();
p1.ID = GUID.NewGUID();
PersonRepository.Insert(p1);
Указывая GUID до времени установки можно сохранить обратно в базу данных при вставке последующих детей записи и позволяют совершать их в одной транзакции.
Person p2 = new Person();
p2.ParentID = p1.ID
PersonRepository.Insert(p2);
Вредно для идентификаторов GUID в качестве первичного ключа:
Если ваше приложение не нуждается для сегментирования или группирования было бы лучше придерживаться более простых типов данных, таких как int или bigint.
Многие базы данных имеют свои собственные внутренние реализации, которые пытаются смягчить хранения проблемы, вызванные идентификатор GUID'ы и SQL Server, даже есть функция функция newsequentialid, чтобы помочь с Заказ по UUID'ы для лучшего использования индексов и они, как правило, имеют лучшие ТТХ.
Кроме того, с точки зрения тестера, пользователь или разработчик, работающий с приложением, используя идентификатор на идентификатор GUID позволит существенно улучшить связь. Представьте себе, чтобы прочитать идентификатор по телефону.
В конце концов, если крупномасштабной кластеризации или обфускации URL-адресов требование это's более прагматичный придерживаться автоинкрементные идентификаторы.
Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);
Это, безусловно, самая важная причина для использования идентификаторов GUID.
Тот факт, что вы можете создать уникальный идентификатор без кода зная о или общения с вашим слой персистирования является огромным преимуществом.
Вы можете быть уверены, что человек, объект, который вы создали, на ваш сервер, компьютер, телефон, ноутбук, автономные устройства или уникального во всех ваших серверов по всему миру, однако распространяется.
Вы можете вставить его в любом виде РБД базы данных или нет-sql, файл, отправить его на любой веб-сервис или выбрасывай его сразу, как uneeded
Нет вы никогда не будете столкновение.
Да вставки могут быть немного медленнее, так как индекс может потребоваться повертела.
Да это больше, чем int.
Я знаю, что многие люди убеждены о авто Инк ИНЦ и это спорная тема с администраторов баз данных
Но я не государство достаточно сильно, что идентификаторы GUID. Вы должны использовать идентификаторы GUID по умолчанию в любом приложении.
авто Инк ИНЦ имеют много недостатков
Вы используете не-SQL и распределенных БД. Вы просто не можете говорить на всех других случаях, чтобы выяснить, что следующее число.
Вам использовать системную очередь сообщений. Вещи нужны идентификаторы, прежде чем они попали в БД
Вы создаете несколько объектов и редактировать их перед сохранением. Каждый требует идентификатор, прежде чем вы попали в дБ
Вы хотите удалить и повторно вставить строки. Убедитесь, что вы Дон'т прикинь вашего авто Инк идентификаторы и закончатся!
Вы хотите, чтобы не подвергать, сколько заказов Вы предприняли в этом году для каждого пользователя
Вы хотите, чтобы переместить анонимизированных данных от производства до тестирования и сохранить отношения в целости. Но не удалить все имеющиеся экспериментальные данные.
Вы хотите объединить один продукт арендатора в арендованную базу данных, но у каждого есть порядка 56.
Вы создаете объекты, которые сохраняются, но эфемерное. (невыполненных заказов) опять же, не использовали все ваши ИНЦ СО всякой всячиной, которая уже не существует.
Список бесконечен, и все они реальные проблемы, которые происходят с людьми все время. в отличие от бежать вне дискового пространства, из-за чуть большего размера ФК седла
Наконец, массовые проблемы с ИНЦ является вы бежите из них!!! ок, в теории нет, есть множество. Но на практике вы делаете, потому что люди Дон'т относиться к ним как случайные числа, не имеющим смысла. они делают такие вещи, как
О, я не'т хотите, чтобы клиенты думают, что мы новый. старт на 10 000
Мне пришлось импортировать загрузки данных, так что я просто поднял семян на 1м, поэтому мы знаем, что импортируется
нам нужна категория'ы данных. каждый период начинается со следующего миллиона, чтобы мы могли использовать первые цифры как магическое число
Я удалил и повторно импортировать все данные с новыми идентификаторами. Да даже журналы аудита.
используйте этот номер, который является составной ключ, а код это другое дело
Я'd не сказать, нет, Дон'т использовать идентификаторы GUID в качестве первичных ключей. Я'м на самом деле имеем дело с такими БД сейчас, и они являются одной из основных причин проблем с производительностью.
Лишние 12 байт сложить быстро; помните, большинство ПКС будет ФКС в другие таблицы, и всего за три ФКС в таблице, теперь у вас есть 48 байт дополнительной для каждой строки. Что добавляет вверх в таблице и в индексах. Он также добавляет в дискового ввода-вывода. эти дополнительные 12 байтов должны быть прочитаны и записаны.
И если вы'повторно не используя последовательные идентификаторы GUID и ПКС группируются (что и происходит по умолчанию), то SQL будет время от времени придется перемещать целые страницы данных, чтобы выжать больше в право на "месте.&я для транзакций базы данных с большим количеством вставок, обновлений и удалений, все идет быстро.
Если вам нужен какой-то уникальный идентификатор для синхронизации или что-то, добавить столбец GUID. Просто Дон'т сделать это на ПК.
Я понимаю, что эти идентификаторы GUID используются для идентификации объектов на уровне приложения. Они также хранятся в качестве первичного ключа на уровне базы данных.
Что's, где вы должны остановить прямо там, и переосмыслить.
Первичный ключ базы данных не должны иметь экономический смысл. Она должна быть бессмысленной по определению.
Чтобы добавить идентификатор GUID в качестве ключа бизнес, и обычный первичный ключ (обычно длинный инт) в качестве первичного ключа базы данных. Вы всегда можете поставить уникальный индекс по GUID, чтобы гарантировать уникальность.
Что'ы говорил теории баз данных конечно, но это's хорошая практика, а также. Я'вэ рассматриваются базы данных, первичные ключи имели экономический смысл (один клиент думал, чтобы сэкономить ресурсы базы данных, используя их как сотрудник чисел, числа клиентов и т. д. и т. д. например) и это всегда приводит к беде.
Всегда использовать базу данных автоматически, автоинкрементные первичные ключи(ПКС).
Зачем использовать автоинкрементные вместо GUID/UUID и?
Но как тогда обрабатывать сегменты, кластеры и т. д.?
3-колонки ПК для кластеризованной таблице, может быть...
DB | SH | KEY |
----|----|---------|
01 | 01 | 1234567 |
Но Что Насчет...?
Несколько обращений к базе данных-большинство приложений не нужно однозначно идентифицировать записи, пока он'ы внесены в базу данных так, что поток/сессия/все работает только на одном одновременно. Если приложение действительно нужна эта возможность, использовать приложение, созданное временное ПК что не отправляется в базу данных. Давайте тогда на базе выразились's собственное авто-инкремент кол-во в ряду, когда он'ы вставлен. Вставки будут использовать временную ПК во время обновления и удаления будут использовать постоянный ПК назначается базой данных.
Производительность-компьютеры могут обрабатывать простые числа гораздо быстрее, чем все остальное, потому что значительно крупнее домена, если возможные значения каждого элемента в идентификатор GUID(37) и целое (10). Помните также, что каждый персонаж в идентификатор GUID должен сначала быть преобразован в ряд для манипуляций со стороны процессора.
Общие злоупотребления первичные ключи Пкс имеют только одну цель... абсолютно однозначно идентифицировать строку в таблице. Все остальное-это слишком часто злоупотребляют.
Обнаружение Отсутствующих Записей
Сортировка
Вроде ничего, есть свои преимущества и недостатки, чтобы делать это:
Хороший:
Ваши ключи всегда имеют одинаковую длину (очень больших баз данных может иметь очень большие ключи)
Уникальность-это почти гарантировано - даже если вы'вновь создавая их из отдельной системы, и/или не'т Читать последний ID из базы данных
Плохая:
Как уже упоминалось много выше - более крупные индексы и хранения данных.
Вы можете'т того, по ID, вы должны заказать что-то другое. Больше индексов, вероятно, менее эффективными.
Они're более менее удобочитаемое. Целые числа, как правило, легче разобрать, запомнить и набрать людей. Используя идентификаторы GUID в качестве идентификаторов в предложениях where для нескольких соединяемых таблиц может сделать вашу голову таять.
Как и все, использовать их там, где это уместно, Дон'т быть догматиком – во многих ситуациях автоматическим приращением числа лучше, иногда идентификаторы GUID являются большими.
Здесь'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 <= _lastSequencePart)
sequencePart = _lastSequencePart + 1;
_lastSequencePart = sequencePart;
}
// shift so that the sequence part fills the most significant 6 bytes of the result value
sequencePart = (sequencePart << 16);
// randomize the lowest 2 bytes of the result, just in case two different client PCs call GetNewId() at exactly the same time
var randomPart = Random.Next() & 0xFFFF;
return sequencePart + randomPart;
}
// used if you want to generate an Id value for a historic time point (within the start and end dates)
// there are no checks, compared to calls to GetNewId(), but the chances of colliding values are still almost zero
public static long GetIdForDateTime(DateTime dt)
{
if (dt < PeriodStartDate || dt > PeriodStartDate)
throw new ArgumentException($"value must be in the range {PeriodStartDate:dd MMM yyyy} - {PeriodEndDate:dd MMM yyyy}");
var sequencePart = GetSequenceValueForDateTime(dt.ToUniversalTime());
var randomPart = Random.Next() & 0xFFFF;
return ( sequencePart << 16 ) + randomPart;
}
// Get a 6 byte sequence value from the specified date time - startDate => 0 --> 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;
}
}
Да, вы можете использовать GUID в качестве первичного ключа. Недостаток-размер и быстрого фрагментации индекса.
Если вам нужна уникальность по базам данных (например, кластер) целое число является предпочтительным.