Первичный ключ UUID в Postgres, что влияет на производительность?

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

В СУБД, использующих кластерное хранилище для записей в таблице, указано, что использование UUID увеличивает стоимость вставок из-за необходимости чтения с диска, чтобы найти страницу данных, в которую будет выполняться вставка, после того, как таблица слишком велика для хранения в памяти. Насколько я понимаю, Postgres не поддерживает кластеризацию строк на вставках, поэтому я предполагаю, что в Postgres, использующем UUID PK, не повредит производительность этой вставки.

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

Предполагая, что я правильно понимаю влияние производительности на индекс, есть ли способ исправить это или UUID просто не хороший PK на большой, не разделенной таблице?

Ответ 1

Как я понимаю, Postgres не поддерживает кластеризацию строк при вставках

Правильно в данный момент. К сожалению.

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

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

  • uuid в 4 раза шире типичного 32-битного целочисленного синтетического ключа, поэтому строка для записи составляет 12 байт больше, и вы можете поместить меньше строк в заданный объем ОЗУ

  • Индекс b-дерева, который реализует первичный ключ, будет в 4 раза больше (по сравнению с 32-разрядным ключом), занимая больше времени для поиска и требуя кэширования большего количества памяти. Он также нуждается в более частых разбиениях страниц.

  • Писания будут иметь тенденцию быть случайными в индексах, а не присоединяться к горячим, недавно доступным строкам

Есть ли способ исправить [влияние производительности на индекс] или UUID просто не хороший PK на большой, не разделенной таблице?

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

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

Ответ 2

Следует отметить, что вы получите больше сгенерированных WAL, если у вас есть индекс btree для столбца UUID с full_page_writes опцией full_page_writes. Это происходит из-за случайности UUID - значения не являются последовательными, поэтому каждая вставка может коснуться совершенно новой листовой конечной листовой страницы. Вы можете прочитать больше в статье о влиянии полностраничной записи статьи.