Каковы недостатки использования UUID или GUID в качестве первичного ключа?

61

Я хотел бы построить распределенную систему. Мне нужно хранить данные в базах данных, и было бы полезно использовать UUID или GUID в качестве первичного ключа для некоторых таблиц. Я предполагаю, что у этого дизайна есть недостатки, так как UUID / GUID довольно большой, и они почти случайны. Альтернатива - использовать автоматически увеличенный INT или LONG.

Каковы недостатки использования UUID или GUID в качестве первичного ключа для моих таблиц?

Я, вероятно, буду использовать Derby / JavaDB (на клиентах) и PostgreSQL (на сервере) в качестве СУБД.

Jonas
источник
Почему это было бы полезно? На какие недостатки вы больше всего ориентируетесь? Ответ на каждый вопрос БД такой расплывчатый: «это зависит». Можете ли вы дать нам более подробную информацию? Вы больше всего заинтересованы в чтении или записи производительности? о каком уровне распространения идет речь?
Брайан Баллсун-Стэнтон
@Brian: UUID в распределенных системах полезен, поскольку вы можете создать первичный ключ на клиентах и ​​затем асинхронно загрузить данные на сервер. Я в основном думаю о недостатках производительности чтения. Использование многих JOIN для UUID не может быть хорошим? Например, клиент добавляет элемент (UUID, имя, поставщик, создатель) в систему инвентаризации, а затем локальная база данных синхронизируется с центральной базой данных на сервере.
Джонас
1
Я думаю, что без каких-либо более разъясняющих комментариев по этому поводу, это будет самое большее «это зависит». Без них я пойду на VtC.
Jcolebrand
Есть статья, в которой говорится о влиянии GUID и не-GUID на кластерные индексы в SQL Server, который может оказаться интересным, даже если он связан с другим продуктом SQL: x.co/Twpp
Jeff
Я заметил, что Derby doc не перечисляет UUID как тип данных. Возможно, вы захотите рассмотреть альтернативу, такую ​​как H2 Database Engine (чистая база данных Java, такая как Derby), которая перечисляет тип данных UUID . Конечно, Postgres имеет отличную поддержку для эффективного хранения , индексации и генерации значений UUID.
Василий Бурк

Ответы:

29

Это зависит от вашей функции генерации и размера финальных столов

GUID предназначены для глобально уникальных идентификаторов. Как обсуждалось в документации Postgres 8.3 , нет методологий, универсально подходящих для генерации этих идентификаторов, но postgreSQL поставляется с несколькими более полезными кандидатами.

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

С функциональной точки зрения длина ключа обычно не является проблемой в любой современной системе, в зависимости от количества операций чтения и размера таблицы. В качестве альтернативной методологии автономные клиенты могут пакетировать новые записи без первичного ключа и просто вставлять их при повторном подключении. Поскольку postgreSQL предлагает тип данных «Serial», клиентам никогда не потребуется определять ID, если они могут выполнять простую запись в базу данных.

Брайан Баллсун-Стэнтон
источник
3
Черт возьми, ты ушел и позволил Брайану ответить на вопрос. Да, требование «автономных обновлений» полностью изменило всю концепцию.
Jcolebrand
Muahahahaah! :: злобно крутит усы ::
Брайан Баллсун-Стэнтон
1
Даже с автономной записью можно было бы использовать INT. Например, используя два столбца, {Node_ID, Item_ID}где у каждого узла есть Node_ID, и Item_IDавтоматически увеличивающийся для каждого узла.
Йонас
@Jonas ~ Да, это возможно. Однако одна из причин, по которой большинство людей даже рассматривают идентификаторы GUID, заключается в репликации содержимого по всему миру в другие базы данных. Я имею в виду сам термин скорее QED там.
Jcolebrand
Что касается архитектуры master / slave или клиентов с разреженным соединением + архитектуры главного сервера, можно ли использовать global_id (SERIAL) на ведущем устройстве и global_id (BIGINT) + local_id (SERIAL) на ведомых устройствах. Подчиненные устройства выполняют свою локальную работу, используя local_id и фиксируя, когда они могут, по отношению к ведущему устройству, ведущее устройство получает данные и предоставляет ему global_id, которое оно возвращает подчиненному, ведомое устройство обновляет поле global_id (для справочного использования при обращении к серверу или другим рабы).
Михай Станку
22

Еще один совет - никогда не используйте GUID как часть кластерного индекса. Идентификаторы GUID не являются последовательными, поэтому, если они являются частью кластерного индекса, при каждом добавлении новой записи базе данных потребуется переставлять все страницы своей памяти, чтобы найти подходящее место для вставки, в случае автоматического увеличения int (bigint) она будет только последняя страница.

Теперь, если мы посмотрим на некоторые реализации БД: 1.) MySQL - первичные ключи кластеризованы, без возможности изменить поведение - рекомендуется вообще не использовать GUID здесь 2.) Postgres, MS-SQL - вы можете сделать GUID как первичный ключ некластеризован и использует другое поле в качестве кластерного индекса, например, autoincrement int

Росс Иванцив
источник
То, что вы предлагаете для Postgres, можно сделать и в MySQL, с несколько иной структурой - auto_increment PK (кластерный ключ), GUID с уникальным индексом (некластеризованный).
ypercubeᵀᴹ
Это не всегда так. В зависимости от пропускной способности дисковой системы, узким местом может быть синхронизация доступа к этой последней странице. blog.kejser.org/2011/10/05/…
mwilson
2
«В отличие от Microsoft SQL Server, кластеризация по индексу в PostgreSQL не поддерживает этот порядок. Для поддержания порядка необходимо повторно применить процесс CLUSTER». Как CLUSTER ON улучшает производительность индекса
bartolo-otrit
Более сжатая версия информации @ bartolo-otrit связана с: stackoverflow.com/a/4796685/1394393 . Этот ответ на самом деле не кажется мне актуальным, так как этот вопрос касается PG, и он, похоже, предполагает сходство с SQL Server и MySQL, которых не существует.
jpmc26
database would need to rearrange all its memory pages to find the right place for insertion=> Я не думаю, что это имеет место с Postgres, поскольку кластеризация является необязательной, а новые строки хранятся неупорядоченными.
Flavien
3

По-разному.

Серьезно, со всем, что вы дали, это примерно настолько, насколько вы можете пойти.

Почему было бы полезно использовать UUID? Почему вы не будете использовать INT? Почему вы не можете просто индексировать UUID позже? Вы понимаете, что значит иметь отсортированный список с ключом UUID и вставлять случайный (непоследовательный) UUID после нескольких миллионов строк?

На какой платформе это будет работать? Сколько дисков? Сколько пользователей? Сколько записей?

Jcolebrand
источник
7
Как я писал в своем комментарии, если я использую UUID, клиенты могут добавлять строки в базу данных без подключения к серверу, а затем синхронизироваться с сервером. Я не могу этого сделать, если я использую INT для первичного ключа, потому что несколько клиентов могут использовать один и тот же первичный ключ для разных элементов. Что ж, бесполезно сортировать список по столбцу UUID, было бы более полезно отсортировать его по столбцу отметки времени. Нет, я не знаю, что означает вставка случайного непоследовательного UUID после нескольких миллионов строк, поэтому я задаю этот вопрос.
Джонас
Приложение будет написано на Java, а клиенты будут использовать Windows, Mac или Linux. Клиенты будут использовать обычные настольные компьютеры, которые обычно имеют один диск. Количество пользователей и записей зависит от того, сколько клиентов я получу, но это будет около 5000 на клиента и клиента.
Джонас
1
Автономный комментарий изменил все. Посмотрите, что больше деталей делает?
Jcolebrand