#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.