Будет ли UUID в качестве первичного ключа в PostgreSQL давать плохую производительность индекса?
Я создал приложение в Rails на Heroku, используя базу данных PostgreSQL.
Он имеет несколько таблиц, предназначенных для синхронизации с мобильными устройствами, где данные могут быть созданы в разных местах. Поэтому у меня есть поле uuid, которое является строкой, хранящей GUID в дополнение к первичному ключу автоматического приращения. Uuid-это тот, который передается между сервером и клиентами.
Я понял после реализации механизма синхронизации на стороне сервера, что это приводит к проблемам с производительностью при необходимости постоянно сопоставлять UUIDid (при написании объектов мне нужно запросить uuid, чтобы получить идентификатор перед сохранением и наоборот при отправке данных).
теперь я думаю о переключении на использование только UUID в качестве первичного ключа, что делает запись и чтение намного проще и быстрее.
Я читал, что UUID в качестве первичного ключа иногда может давать плохую производительность индекса (фрагментацию индекса) при использовании кластеризованного индекса первичного ключа. Страдает ли PostgreSQL от этой проблемы или можно использовать UUID в качестве первичного ключа?
сегодня у меня уже есть столбец UUID, поэтому хранение будет лучше, потому что я отбрасываю обычный столбец id.
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, я думаю, разница было бы несуществующим, так как твердотельные накопители по дизайну всегда имеют случайный доступ (без поиска головки, без участия механических частей, просто чистое электричество)