Каково Ваше мнение об использовании UUID в качестве идентификаторов строк базы данных, особенно в веб-приложениях?

Я всегда предпочитал использовать длинные целые числа в качестве первичных ключей в базах данных, для простоты и (предполагаемых) скорости. Но при использовании остальное или Rails-как URL-схема для экземпляров объектов, я бы в конечном итоге с URL-адресами, как это:

http://example.com/user/783

и тогда предполагается, что есть и пользователи с идентификаторами 782, 781, ..., 2, и 1. Предполагая, что веб-приложение достаточно безопасно, чтобы запретить людям вводить другие номера для просмотра других пользователей без авторизации, простой последовательно назначенный суррогатный ключ также "утекает" общее количество экземпляров (старше этого), в данном случае пользователей, которые могут быть привилегированной информацией. (Например, я пользователь #726 в stackoverflow.)

б UUID / GUID будет лучшим решением? Тогда я мог бы настроить URL-адреса следующим образом:

http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66

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

стоит ли эта выгода затрат и сложности реализации UUID для веб-адресуемых экземпляров объектов? Я думаю, что я все равно хочу использовать целочисленные столбцы в качестве базы данных PKs только для ускорения соединений.

существует также вопрос о представлении UUIDs в базе данных. Я знаю, что MySQL хранит их как 36-символьные строки. Postgres, похоже, имеет более эффективное внутреннее представление (128 бит?) но сам я не пробовал. У кого-нибудь есть опыт в этом?


Update: для тех, кто спросил об использовании имени пользователя в URL (например,http://example.com/user/yukondude), это отлично работает для экземпляров объектов с уникальными именами, но как насчет миллионов объектов веб-приложений, которые действительно могут быть идентифицированы только по номеру? Заказы, транзакции, счета-фактуры, дубликаты имен изображений, вопросы stackoverflow, ...

15 ответов


Я не могу сказать о веб-части вашего вопроса. Но UUID отлично подходят для n-уровневых приложений. Генерация ПК может быть децентрализована: каждый клиент генерирует свой собственный ПК без риска столкновения. И разница в скорости вообще небольшая.

убедитесь, что ваша база данных поддерживает эффективный тип данных хранения (16 байт, 128 бит). По крайней мере, вы можете кодировать строку UUID в base64 и использовать char(22).

Я широко использовал их с Firebird и делать рекомендовать.


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


Я могу ответить вам, что в SQL server, если вы используете тип данных uniqueidentifier (GUID) и используете функцию NEWID() для создания значений, вы получите ужасную фрагментацию из-за расколов страниц. Причина в том, что при использовании NEWID() генерируемое значение не является последовательным. SQL 2005 добавил функцию NEWSEQUANTIAL (), чтобы исправить это

один из способов по-прежнему использовать GUID и int-иметь guid и int в таблице, чтобы guid отображался в int. guid используется внешне, но int внутри БД

457180FB-C2EA-48DF-8BEF-458573DA1C10    1
9A70FF3C-B7DA-4593-93AE-4A8945943C8A    2

1 и 2 будут использоваться в соединениях и GUID в веб-приложение. Эта таблица будет довольно узкой и должна быть довольно быстрой для запроса


Почему пару первичного ключа с Ури?

Почему бы вашему ключу URI не быть читаемым человеком (или не угадываемым, в зависимости от ваших потребностей), и основанное на вашем основном индексе целое число, таким образом, вы получаете лучшее из обоих миров. Много программного обеспечения блога делает это, где открытый идентификатор записи идентифицируется "слизняком", а числовой идентификатор скрыт внутри системы.

дополнительным преимуществом здесь является то, что теперь у вас есть действительно хорошая структура URL, которая хороша для ОПТИМИЗАЦИЯ ПОИСКОВЫХ СИСТЕМ. Очевидно, для транзакции это не очень хорошо, но для чего-то вроде stackoverflow это важно (см. URL up top...). Получить уникальность не так уж сложно. Если вы действительно обеспокоены, сохраните хэш слизняка внутри таблицы где-нибудь и выполните поиск перед вставкой.

edit: Stackoverflow не совсем использует систему, которую я описываю, см. комментарий парня ниже.


а не URL-адреса, как это:

http://example.com/user/783

почему бы не иметь:

http://example.com/user/yukondude

который дружелюбнее к людям и не пропускает этот крошечный бит информации?


вы можете использовать целое число, которое связано с номером строки, но не является последовательным. Например, вы можете взять 32 бита последовательного идентификатора и переставить их с фиксированной схемой(например, бит 1 становится битом 6, бит 2 становится битом 15 и т. д..).
Это будет двунаправленное шифрование, и вы будете уверены, что два разных идентификатора всегда будут иметь разные шифрования.
Очевидно, было бы легко декодировать, если требуется время для создания достаточного количества идентификаторов и получения но, если я правильно понимаю вашу проблему, вы просто не хотите слишком легко отдавать информацию.


мы используем GUID в качестве первичных ключей для всех наших таблиц, поскольку он удваивается как RowGUID для репликации MS SQL Server. Делает это очень легко, когда клиент вдруг открывает офис в другой части мира...


Я не думаю, что GUID дает вам много преимуществ. Пользователи ненавидят длинные, непонятные url.

создать короткий код, который можно сопоставить URL-адрес, или обеспечить уникальное соглашение имя пользователя (http://example.com/user/brianly). Ребята мнению 37signals вероятно, будет издеваться над вами за беспокойство о чем-то подобном, когда дело доходит до веб-приложения.

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


Это также зависит от того, что вы заботитесь о вашем приложении. Для n-уровневых приложений GUID / UUID проще реализовать и легче переносить между различными базами данных. Для создания целочисленных ключей некоторые базы данных поддерживают объект последовательности изначально, а некоторые требуют пользовательской конструкции таблицы последовательности.

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


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

хотя это, вероятно, хорошая идея для архитектурной точки зрения, это затрудняет работу на ежедневной основе. Иногда возникает необходимость делать массовые вставки, и наличие UUID делает это очень сложным, обычно требуя написания курсора вместо простого оператора SELECT INTO.


Я пробовал оба в реальных веб-приложениях.

мое мнение, что предпочтительнее использовать целые числа и иметь короткие, понятные URL-адреса.

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

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


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


Я думаю, что использование GUID было бы лучшим выбором в вашей ситуации. Он занимает больше места, но более безопасен.


Youtube использует 11 символов с кодировкой base64, которая предлагает 11^64 возможности, и они обычно довольно управляемы для записи. Интересно, будет ли это предлагать лучшую производительность, чем полный UUID. UUID, преобразованный в base 64, будет вдвое больше, чем я считаю.

более подробную информацию можно найти здесь: https://www.youtube.com/watch?v=gocwRvLhDf8


пока вы используете систему БД с эффективным хранением, HDD дешев в эти дни в любом случае...

Я знаю, что GUID может быть b*tch для работы с некоторыми временами и приходить с некоторыми накладными расходами запроса, однако с точки зрения безопасности они являются спасителем.

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