Будет ли UUID в качестве первичного ключа в PostgreSQL давать плохую производительность индекса?

Я создал приложение в Rails на Heroku, используя базу данных PostgreSQL.

Он имеет пару таблиц, предназначенных для синхронизации с мобильными устройствами, где данные могут быть созданы в разных местах. Поэтому у меня есть поле uuid, которое является строкой, хранящей GUID в дополнение к первичному ключу с автоматическим добавлением. Uuid - это тот, который передается между сервером и клиентами.

Я понял после реализации механизма синхронизации на стороне сервера, что приводит к проблемам с производительностью при необходимости сопоставлять между uuid ↔ id все время (при записи объектов мне нужно запросить uuid, чтобы получить идентификатор раньше сохранение и наоборот при отправке данных).

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

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

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

Ответ 1

(Я работаю над Postgres Heroku)

Мы используем UUID в качестве основных ключей на нескольких системах, и он отлично работает.

Я рекомендую вам использовать расширение uuid-ossp, и даже если postgres генерируют UUID для вас:

heroku pg:psql
psql (9.1.4, server 9.1.6)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

dcvgo3fvfmbl44=> CREATE EXTENSION "uuid-ossp"; 
CREATE EXTENSION  
dcvgo3fvfmbl44=> CREATE TABLE test (id uuid primary key default uuid_generate_v4(), name text);  
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE  
dcvgo3fvfmbl44=> \d test
                 Table "public.test"  
Column | Type |              Modifiers              
--------+------+-------------------------------------  
id     | uuid | not null default uuid_generate_v4()  name   | text |  
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)

dcvgo3fvfmbl44=> insert into test (name) values ('hgmnz'); 
INSERT 0 1 
dcvgo3fvfmbl44=> select * from test;
                  id                  | name  
--------------------------------------+-------   
 e535d271-91be-4291-832f-f7883a2d374f | hgmnz  
(1 row)

Показатели эффективности EDIT

Это всегда будет зависеть от вашей рабочей нагрузки.

Integer первичный ключ имеет преимущество локальности, где подобные данные сближаются. Это может быть полезно, например, для запросов типа диапазона, таких как WHERE id between 1 and 10000, хотя конфликт блокировок хуже.

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

Вы много пишете в этой таблице, и эта таблица очень большая? Возможно, хотя я не измерял это, что есть последствия для поддержания этого индекса. Для множества наборов данных UUID просто хороши, и использование UUID в качестве идентификаторов имеет некоторые приятные свойства.

Наконец, я не могу быть наиболее квалифицированным человеком для обсуждения или совета по этому поводу, так как я никогда не запускаю таблицу достаточно большой с ПК UUID, где это стало проблемой. YMMV. (Сказав это, я хотел бы услышать о людях, которые сталкиваются с проблемами с этим подходом!)

Ответ 2

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

Автоинкремент естественно сортируется по дате, поэтому, когда используется автоинкремент, данные хранятся хронологически на диске (см. B-Tree), что ускоряет чтение (не ищет HDD). Например, если вы укажете всех пользователей, что естественный порядок будет создан по дате, который будет таким же, как автоинкремент, и поэтому запросы диапазона будут выполняться быстрее на жестких дисках, а на SSD, я полагаю, разница будет несущественной, поскольку SSD файлы по дизайну всегда случайны доступ (без поиска головы, без участия механических частей, чистое электричество)