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


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

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

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

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

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

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

2 52

2 ответа:

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

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

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

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)

редактировать последствия для производительности

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

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

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

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

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

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

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