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

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

http://example.com/user/783

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

Будет ли UUID / GUID лучшим решением? Затем я мог бы настроить такие URL-адреса:

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

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

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

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


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

Ответов (15)

Решение

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

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

Я много использовал их с Firebird и рекомендую.

Вместо таких URL-адресов:

http://example.com/user/783

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

http://example.com/user/yukondude

Что более дружелюбно для людей и не дает утечки такой крохотной информации?

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

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

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

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

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

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

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

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

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

Я могу ответить вам, что в SQL-сервере, если вы используете тип данных 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 будет лучшим выбором в вашей ситуации. Он занимает больше места, но более безопасен.

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

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

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

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

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

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

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

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

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

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

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

Зачем связывать ваш первичный ключ с вашим URI?

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

Дополнительным преимуществом здесь является то, что теперь у вас есть действительно хорошая структура URL-адресов, которая хорошо подходит для SEO. Очевидно, для транзакции это нехорошо, но для чего-то вроде stackoverflow это важно (см. URL вверху ...). Получить уникальность не так уж и сложно. Если вас это действительно беспокоит, сохраните хэш слага где-нибудь в таблице и выполните поиск перед вставкой.

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