Какую часть идентификатора GUID лучше всего сохранить?

#c# #guid #identifier

#c# #идентификатор guid #идентификатор

Вопрос:

Мне нужно сгенерировать уникальный идентификатор, и я рассматривал Guid.NewGuid возможность сделать это, что генерирует что-то вроде формы:

 0fe66778-c4a8-4f93-9bda-366224df6f11
 

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

Вопрос в том, является ли один конец идентификатора GUID более предпочтительным, чем остальные, с точки зрения уникальности? Должен ли я обрезать начало, конец или удалять части из середины? Или это просто не имеет значения?

Комментарии:

1. Это хороший вопрос. Я склонен использовать средние биты, но я не верю, что есть разница.

2. Я проведу эксперимент монте-Карло и опубликую результаты.

3. UUID версии 4 имеют вид xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx с любыми шестнадцатеричными цифрами для x, но только с одной из 8, 9, A или B для y. например, f47ac10b-58cc-4372-a567-0e02b2c3d479.

4. Если вы не можете сохранить все это (а вы действительно должны!), Подумайте о том, чтобы взять 128-битное значение GUID и перекодировать его во что-то более компактное, что вы можете втиснуть в свое более короткое строковое поле.

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

Ответ №1:

Вы можете сэкономить место, используя вместо этого строку base64:

 var g = Guid.NewGuid();
var s = Convert.ToBase64String(g.ToByteArray());

Console.WriteLine(g);
Console.WriteLine(s);
 

Это сэкономит вам 12 символов (8, если вы не использовали дефисы).

Ответ №2:

Сохраните все это.

По ссылке выше:

 * Four bits to encode the computer number,
* 56 bits for the timestamp, and
* four bits as a uniquifier.
 

вы можете переопределить идентификатор Guid, чтобы он соответствовал вашим потребностям.

Комментарии:

1. Включенная информация не имеет отношения к UUID версии 4. Могут быть причины для сохранения всего идентификатора GUID, но это фактически пустая ссылка — и даже при том, что это хорошее чтение, соответствующая (и точная) информация должна присутствовать в ответе.

Ответ №3:

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

 double numBirthdays = 365;  // set to e.g. 18446744073709551616d for 64 bits
double numPeople = 23;      // set to the maximum number of GUIDs you intend to store
double probability = 1; // that all birthdays are different 
for (int x = 1; x < numPeople; x  ) 
   probability *= (double)(numBirthdays - x) / numBirthdays; 

Console.WriteLine("Probability that two people have the same birthday:");
Console.WriteLine((1 - probability).ToString());
 

Однако часто вероятность столкновения выше, потому что, на самом деле, идентификаторы GUID, как правило, НЕ случайны. Согласно статье GUID в Википедии, существует пять типов идентификаторов GUID. 13-я цифра указывает, какой у вас тип идентификатора GUID, поэтому она, как правило, не сильно меняется, а два верхних бита 17-й цифры всегда фиксированы 01 .

Для каждого типа идентификатора GUID вы получите разную степень случайности. Версия 4 (13-я цифра = 4) полностью случайна, за исключением цифр 13 и 17; версии 3 и 5 фактически случайны, поскольку они являются криптографическими хэшами; в то время как версии 1 и 2 в основном НЕ случайны, но некоторые части довольно случайны в практических случаях. «Ошибка» для идентификаторов GUID версий 1 и 2 заключается в том, что многие идентификаторы GUID могут поступать с одной и той же машины и в этом случае будут иметь большое количество идентичных битов (в частности, последние 48 битов и многие временные биты будут идентичны). Или, если несколько идентификаторов GUID были созданы одновременно на разных машинах, у вас могут возникнуть коллизии между временными битами. Итак, удачи в безопасном усечении этого.

У меня была ситуация, когда мое программное обеспечение поддерживало только 64 бита для уникальных идентификаторов, поэтому я не мог использовать идентификаторы GUID напрямую. К счастью, все идентификаторы GUID были типа 4, поэтому я мог получить 64 бита, которые были случайными или почти случайными. У меня было два миллиона записей для хранения, и алгоритм дня рождения указал, что вероятность столкновения составляет 1,08420141198273 x 10 ^ -07 для 64 бит и 0,007 (0,7%) для 48 бит. Следует предположить, что это наилучший сценарий, поскольку уменьшение случайности обычно увеличивает вероятность столкновения.

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

Комментарии:

1. Я ценю доказательство. Я видел алгоритм раньше, но никогда не рассматривал возможность его использования таким образом. Спасибо за урок.

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

3. Кроме того, для чего-то подобного newsequentialid() выбор определенных битов почти на 0% случаен:}

Ответ №4:

Я согласен с Робом — сохраните все это.

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

Для получения дополнительной информации см. NHibernate POID Generators revealed и документацию по алгоритмам Guid.

ПРИМЕЧАНИЕ: Guid.Comb предназначен для повышения производительности MsSQL

Ответ №5:

Усечение идентификатора GUID — плохая идея, почему, пожалуйста, смотрите В этой статье.

Вам следует подумать о создании более короткого идентификатора GUID, поскольку Google предлагает некоторые решения для. Похоже, что эти решения предполагают использование идентификатора GUID и изменение его для представления в полном 255-битном ascii.