Postgresso 35 — спецвыпуск: PostgreSQL 14
Пресс-релиз PostgreSQL обширен и основателен. Есть и выжимка (highlights), в которой после бурных обсуждений в рассылках выделили главное.
Статей о 14-й много. Мы смотрели и разрозненные статьи и целые сериалы:
обзоры коммитфестов Павла Лузанова (5 серий),
waiting for PostgreSQL 14 Хуберта 'depesz' Любашевского (18),
микрообзоры Postgres 14 highlights Мишеля Пакье (Michael Paquier) (5),
в блоге Fujitsu OSS (5).
Кроме того есть пространная статья-справочник от HPE: PostgreSQL 14 New Features With Examples (Beta 1).
Начнём со статей, в которых авторы стараются охватить версию 14 в целом. Но перед этим разомнёмся
в облаках и контейнерах
PostgreSQL 14 on Kubernetes (with examples!)
Джонатан Кац (Jonathan S. Katz, Crunchy data) показывает, как инсталлировать кранчевский оператор PGO (горячо рекомендует с quickstart) и запускает PostgreSQL 14.
После этого в качестве примера он демонстрирует асинхронные запросы к сторонним таблицам — возможность, появившуюся в 14-й версии (через postgres_fdw, который научился исполнять запросы параллельно). Он создаёт целых 3 кластера: Носорог-1, Носорог-2 и Гиппопотам, настраивает postgres_fdw на Гиппо, создаём на Носорогах таблички через IMPORT FOREIGN SCHEMA (тоже новая фича 14-й) и, наконец, собирая данные с обоих носорогов, убеждается, что данные собираются асинхронно:
EXPLAIN ANALYZE SELECT avg(x.stat) FROM (
SELECT data['stat']::float AS stat FROM rhino1.stats
UNION ALL
SELECT data['stat']::float AS stat FROM rhino2.stats
) x;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
Aggregate (cost=424.80..424.81 rows=1 width=8) (actual time=13700.998..13701.000 rows=1 loops=1)
-> Append (cost=100.00..412.00 rows=5120 width=8) (actual time=2.937..13410.193 rows=4000000 loops=1)
-> Async Foreign Scan on stats (cost=100.00..193.20 rows=2560 width=8) (actual time=1.394..5337.504 rows=2000000 loops=1)
-> Async Foreign Scan on stats stats_1 (cost=100.00..193.20 rows=2560 width=8) (actual time=1.760..4807.722 rows=2000000 loops=1)
Planning Time: 1.019 ms
Execution Time: 13704.199 ms
Чуть позже Джонатан написал статью-апдейт: с использованием вышедшего PGO 5.0: Multi-Cluster Postgres Federation on Kubernetes with Postgres 14 Using GitOps.
Неспроста автор придумал пароль для серверов — datalake. Он явно намекает: для озёр данных такая архитектура годная. Делает он во второй статье вот что:
создаёт на 3 кластерах по 3 секции (используя заодно подтип datemultirange
типа multirange, появившегося в 14-й), чтобы не без изящества автоматически раскладывать по ним данные с соответствующих 3 кластеров. А дальше при помощи логической репликации обустраивает простенький мультимастер — на все 3 ноды пишутся данные и сразу синхронизируются по всем 3 кластерам. Не успокоившись, он «масштабирует» «мультимастер» до 4 узлов — тоже раскладывая данные по полочкам. Это, конечно, только наглядный пример, никакой настоящей гарантии консистентности там нет, но вообще в релизе PostgreSQL 14 аж 10 пунктов относятся к логической репликации.
How We Shipped PostgreSQL 14 on Azure Within One Day of its Release
В Citus хвалятся тем, что новую версию развернули как «Гипермосштабирование» в облаках Azure за 1 день — как только был опубликован релиз. Озгун Эрдоган (Sic! — Ozgun Erdogan, Citus Data) пишет о любимых новых фичах 14-й, а они, конечно, связаны с задачами Citus. То есть работают на производительность и параллелизм. Поэтому полюбит их не только Citus.
Прежде всего полюбилось всё, связанное с масштабированием по числу соединений (connection scaling). В компании считают, что самое узкое место PostgreSQL это масштабирование по снеэпшотам. И что их патчи помогли значительно улучшить ситуацию, особенно в случаях, когда в соединениях ничего не делается (idle
).
Также компания внесла вклад в ускорение восстановления (в 2.4 раза) и ускорение VACUUM на 25% в случае нагрузок, сильно завязанных на процессор.
Совместимость с PostgreSQL 14 они обеспечили не только для самого Citus, но и для других опенсорсных расширений, к которым приложили руку: pg_cron, postgresql-hll (HyperLogLog) и postgresql-topn.
О PostgreSQL 14, едином и неделимом
PostgreSQL 14: PostgreSQL Is Still a Teenager
Кирк Ройбол (Kirk Roybal, instaclustr) считает, что Postgres повзрослел до тинейджера — или не считает: в первоначальной версии статьи, следы которой есть в интернете, название было … Is Still a Tweeny — то есть ребёнок лет 6–12. Но главная причина его удивления — отсутствие фокуса на каких-то направлениях разработки. Я надеялся — говорит Кирк — услышать что-то ошарашивающее, вроде VACUUM больше не нужен! Услышал же я, что множество людей приложило громадные усилия, чтобы улучшить вещи, которые надо было улучшить.
Об этих многочисленных, но не достаточно радикальных (для него) изменениях Кирк и говорит, демонстрируя наблюдательность и взгляд немного под другим углом, чем у многих других. Кажется, это действительно незамыленный взгляд, хотя, по многим пунктам его голос звучит в унисон с голосами, которые мы дальше цитируем. Самым ярким достижением 14-й он считает резкое улучшение масштабируемости по соединениям, когда число соединений переваливает через 5000. Хотя VACUUM и не отменили, но улучшения его, оставшиеся под капотом, он считает, были из самых востребованных сообществом. О некоторых других его соображениях мы упомянем в соответствующем контексте.
Новый GUC — compute_query_id — тоже упомянут. Он позволяет, когда включён, получать id запроса даже без обращения к pg_stat_statements. id запроса вычисляется средствами ядра. Посмотреть его можно и в pg_stat_activity, откуда его берёт EXPLAIN. Или его можно сбросить в лог если сконфигурирован параметр log_line_prefix.
Об этом целая статья ниже.
Major Features: Postgres 14
Этот PDF Брюса Момджана (Bruce Momjian, EDB) — коротенькая презентация. Стоящая внимания: по каждому из пунктов всего-то по схемке (только к btree-индексам — 3), зато они очень наглядные.
- предотвращение распухания btree-индексов;
- улучшения в индексах BRIN;
- масштабирование снэпшотов;
- глобальный id запроса;
- idle_session_timeout;
- роли для операций read-only и write-only;
- улучшения в оптимизаторе;
- параллельное сканирование сторонних таблиц.
Матрица
Любопытная картина складывается, если глянуть на матрицу фич. Пожалуй, это иллюстрация того, как иногда картина крупными мазками не слишком адекватна реальности.
Статистика коммитфестов
Some Interesting statistics about PG-14 contributions
Асан Хади (Ahsan Hadi) из HighGo (вице-президент по разработкам, был старшим директором по продукту Postgres Plus Advanced Server в EDB) решил собрать статистику по коммитам в PostgreSQL 14. Дело доброе: до него этим любил побаловаться Роберт Хаас (Robert Haas), но он считал по годам.
А вот его выбор:
Ну, а Деврим Гюндюз (Devrim Gündüz) поможет
установить 14-ю версию из rpm
Installing PostgreSQL 14 beta/RC on RHEL / Rocky Linux / Fedora and SLES.
Производительность
Postgres 14 и высокие нагрузки
Это видео и презентация Ивана Панченко (зам. гендира Postgres Professional) на весеннем Highload++ в Крокусе-Экспо. Первым пунктом у Ивана стоит повышение масштабируемости по
коннектам. Второе и третье места заняли восходящее удаление (bottom-up delition) и Асинхронный APPEND соответственно.
Между прочим, в своём интервью в качестве Персоны недели Иван на вопрос о любимой фиче отвечает:
Много полезных и важных фич — что в 13-й, что в 14-й —, но ни одна из них не выглядит наиболее важной в сравнении с другими.
(Но почитайте всё интервью: там есть даже про собаку и блоху, объясняющих, как устроено Солнце)
An early look at Postgres 14: Performance and Monitoring Improvements
Лукас Фиттл (Lukas Fittl, pgAnalyze), как и Иван, как и Citus, говорит прежде всего о масштабировании активных и свободных соединений.
Очень понравилось ему новое представление pg_backend_memory_contexts и функция pg_log_backend_memory_contexts (), которые дают возможность заглянуть в память, чтобы понять, какое соединение сжирает больше всего памяти. Другая полезная вещь для диагностики — представление pg_stat_wal. И очень автору понравилось, что guery_id
, которое было в любимом дотошными админами представлении pg_stat_statements, теперь можно использовать и в представлении pg_stat_activity.
О коннектах есть и у Депеша в Waiting for PostgreSQL 14 — Improvements for handling large number of connections:
Депеш приводит список из 7 ссылок на патчи, которые должны обеспечить масштабируемость соединений. Сам он не тестировал, но в комментариях есть ссылка на тесты. По ссылке немало иероглифов, но, вроде, ясно, что на 5000 соединений 14-й выиграл у 13-го 37% на TPS.
Мониторинг и «прозрачность»
В упомянутой статье Кирка прозрачность (переведу таким вольным образом visibility) отобразилась в виде
- Статус операции COPY появился в
pg_stat_progress_copy
. - Статус WAL в
pg_stat_wal
. - Статус репликации в
pg_stat_replication_slots
. - Статус обработки запроса бэкендом в
pg_backend_memory_contexts
(его также можно сбросить в лог, используяpg_log_backend_memory_contexts
. - Новые колонки в
pg_stat_database
. - Архиватор в
pg_stat_activity
. - В
pg_locks
добавлено время начала ожидания блокировки (lock wait start time). - Добавлено представление
routine_column_usage
вinformation_schema
для отслеживания колонок, на которые ссылаются в выражениях по умолчанию у функций или процедур. - Добавлено
%P
кlog_line_prefix
, чтобы виден был PID лидера группы. - Добавлен серверный параметр
log_recovery_conflict_waits
для отчётов о долгих временах разрешения конфликтов при восстановлении (to report long recovery conflict wait times). - Функция
pg_get_wal_replay_pause_state()
для отчётов о состоянии восстановления. - Функция
pg_xact_commit_timestamp_origin()
, возвращающая timestamp коммитта и начала репликации (replication origin) заданной транзакции. - К записи, возвращаемой
pg_last_committed_xact()
добавлено начало репликации. pg_stat_statements
теперь отслеживает выражения в корне дерева и в листьях (top and nested statements) отдельно.- Для некоторых утилит добавлены кумулятивные флаги –verbose (-vvv) для вывода на экран
Однако список Алексея Лесовского ещё больше: 17 пунктов — Что нового в плане мониторинга в PostgreSQL 14.
И это не просто перечисление, некоторые пункты сопровождаются примерами кода, а некоторые даже эмоциями:
Новое представление pg_backend_memory_contexts — одно из нововведений, которое вызвало у меня противоречивые эмоции… как мне кажется, разработчики перемудрили — достаточно было бы сделать только одну эту [pg_log_backend_memory_contexts()
] функцию (без вьюхи) которая бы принимала идентификатор процесса, но при этом вместо логирования, выводила бы статистику в виде строк.
Monitoring for COPY
Возможность мониторинга операции COPY привлекла внимание Мишеля Пакье (Michael Paquier). COPY TO и COPY FROM нередко занимают много времени, поэтому возможность посмотреть, как идут дела с копированием, не прихоть. В новом системном представлении pg_stat_progress_copy
по одной строке с 8 полями (в статье есть подробности) на каждый бэкенд.
depesz в своих waiting-ах тоже не прошёл мимо COPY: Report progress of COPY commands
Он предупреждает, между прочим, что общее количество байтов в некоторых случаях недоступно — когда ввод идёт с клиента, например.
Using Query ID in Postgres 14 — этому параметру статью посвятили RustProoflabs. Райан Лэмберт (Ryan Lambert) запускает pgbench и сначала смотрит id в pg_stat_statements
(для такой возможности compute_query_id
надо установить в postgresql.conf
в auto
или on
).
После этого Райан открывает параллельно 3 сессии: в двух он сталкивает UPDATE-транзакции так, что вторая натыкается на блокировку первой и висит, а в третьей он запускает запрос к pg_stat_statments
и pg_stat_activity
. И убеждается, что так удаётся выловить запрос, который выполняется дольше предыдущих и так и не завершён. Затем Райан демонстрирует два оставшихся способа использования guery_id: в EXPLAIN и в логах, не умолчав о некоторой принципиально нерешаемой (но не слишком критичной) проблеме.
VACUUM
Хорошо сказал выше Кирк, мол, революции не произошло — VACUUM жив, —, но под капотом поменялось немало.
Анализ прочитанного на эту тему показал, что наиболее толковое описание улучшений, связанных с VACUUM, удалось сделать нашему Павлу Лузанову:) в его 5-й серии Заморозки обзоров коммитфестов. Там и много (но концентрированно), и примеры есть. Как, впрочем, и в других его аналогичных обзорах — обзор без VACUUM это каша без соли.
Давно идут разговоры, что VACUUM нужно сделать более агрессивным (и был даже берсерк-автовакуум, предложенный Дорофеем 'Котярой' Пролесковским) — как экстренную меру, когда счётчики xid или multixact приближаются к wraparound. В PostgreSQL 14 в этом случае откладываются до лучших времён чистки индексов, уступая дорогу вакууму. Поведение его управляется константами vacuum_failsafe_age
и vacuum_multixact_failsafe_age
. Но подробных разборов этих ситуаций мы пока не нашли.
(Напомним, что о 64-разрядных идентификаторах транзакций говорят давно, но пока они есть только в коммерческой версии — Postgres Pro Enterprise.)
Выше в Citus хвалились, что ускорили VACUUM на 25% своими патчами. Но об этом (и о восстановлении) у них была и целая статья, которую мы упоминали ещё в Postgresso 30:
Speeding up recovery & VACUUM in Postgres 14
Это статья о патче Citus в основную ветку PostgreSQL, написанная (как и сам патч) Дэвидом Роули (David Rowley), работавшим над этим уже внутри Microsoft. Он переписал внутреннюю функцию compactify_tuples
, которая используется, когда PostgreSQL стартует после внештатного (нечистого) шатдауна (crash recovery), и когда идёт восстановление standby-сервера проигрыванием WAL по их прибытии с primary-сервера.
Эти случаи Дэвид и расписывает, поясняя схемами. Новая версия функции избавляет от ненужной внутренней сортировки кортежей в heap
, поэтому и работает быстрее.
FDW
Эта тема вызвала немало откликов. Прежде всего заинтересовались те, кто движется в сторону шардинга и вообще распараллеливания вычислений.
В статье, которая выше, Асан Хади ставит FDW на первое место в своём списке достижений Postgres 14. И напомним, что Джонатан Кац выбрал асинхронную работу FDW для своего кубернетного примера.
В Postgres OnLine Journal пишут об FDW для Windows: PostgreSQL 14 64-bit for Windows FDWs
Речь о бинарниках file_text_array_fdw и odbc_fdw для PostgreSQL 14 под 64-бытные Windows.
postgres_fdw Enhancement in PostgreSQL 14
Ибрар Ахмед (Ibrar Ahmed, Percona) демонстрирует достижения в PostgreSQL 14 по части FDW на примерах.
Типы (новорожденный и старички)
Multirange Types in Postgres 14
Джонатан Кац (Jonathan S. Katz, Crunchy Data) пишет о мультидиапазонах (multirange) — в PostgreSQL 14 именно они упростили ему и упростят многим их SQL-жизнь: приводит пример «из жизни» — с бронированием встреч. Действительно всего 3 строчки нужно для того, чтобы посмотреть, какие дни свободны. Сначала, конечно, надо забить необходимые данные в таблицу, но сложный рекурсивный запрос не потребуется.
Про мультидиапазонные типы данных довольно развёрнуто пишет и Павел Лузанов в 4-й части коммитфест-обзоров.
Multirange datatypes
В этой заметке Депеш не удовлетворился демонстрационным примером — как создавать колонки multirange и как выглядят результаты запросов к ним, —, а решил разобраться, что с индексами для нового типа. btree
можно создать и использовать для простеньких SELECT. Но depesz хотелось большего — операторов вроде @>
, а вот с этим пока никак. gist/spgist
и gin
тоже отложили на будущее. В комментариях к статье автор патча, Александр Коротков, пояснил, что и btree
пока работает так, как будто дыр между диапазонами нет, используя код для обычных range
, без multi
.
Postgres 14: It’s The Little Things
Типы JSON/JSONB
уже в возрасте, а новость в удобном синтаксисе. Крейг Кирстинс (Creig Kirstiens, Crunchy Data) радуется синтаксису с индексной нотацией JSON (JSON subscripting) — она простая, наглядная, интуитивная. Надо было писать так:
WHERE details->'attributes'->>'color' = 'neon yellow'
а теперь можно так:
WHERE details['attributes']['color'] = '"neon yellow"'
Лузанов поясняет интенции разработчиков более технологично и более исторично: с идеи сделать поддержку индексной нотации для json начался длинный путь [с зимы 2017] работы над этим патчем Дмитрия Долгова. И вот спустя несколько лет такая поддержка появилась. Первый патч создает необходимую инфраструктуру индексной нотации для произвольных типов данных. Второй патч добавляет индексную нотацию к типу hstore, а третий ― к типу JSONB. Теперь вместо специальных функций и операторов можно извлекать необходимые части из JSON-значения. Найдем телефон в контактных данных одного из билетов:
SELECT contact_data, contact_data['phone'] AS phone;
Бэкап и репликация
В блоге Fujitsu обсуждались не все новшества 14-й версии, а те, в разработке которых Fujitsu OSS принимала участие. Они существенные.
Logical decoding of two-phase commits in PostgreSQL 14
PostgreSQL поддерживает двухфазные транзакции аж с версии 8.0, а логическую репликацию с 10.0, но двухфазные коммиты до этого не поддерживались логической репликацией. Команды PREPARE TRANSACTION, COMMIT PREPARED и ROLLBACK PREPARED поддерживались на уровне инстанса, но их не могли корректно декодировать при передаче на реплику. Теперь всё работает. Изменились плагин test_decoding и API.
PostgreSQL работает с памятью в рамках программной архитектуры контекстов. Представление pg_backend_memory_contexts позволяет заглядывать в память, доступную сессии, не используя дебаггер, (это особенно полезно в облачных средах) начиная с TopMemoryContext и спускаясь по деревьям. Это можно сделать не только от суперюзера, но и от ролей, которым это дозволено по GRANT. Кроме того, добавлена одноименная функция pg_backend_memory_contexts (), которая может заглядывать и в чужие сессии (она только под суперюзером). Значения не возвращаются клиенту, а сбрасываются в лог.
REINDEX TABLESPACE
Это значит, что индекс можно перемещать CONCURRENTLY, так как индекс можно перестраивать, перемещая в другое табличное пространство, а не в два этапа: перестройка, потом перемещение — меньше вероятность, что пространства не хватит. При этом разрешая одновременное чтение и запись во время переиндексации, поскольку операция накладывает блокировку SHARE UPDATE EXCLUSIVE на индекс и родительскую таблицу. Подобная судьба (добавка CONCURRENTLY) ждала CLUSTER и VACUUM FULL, но не дождалась: релиз вышел.
Fun with Hashes
Здесь даже есть небольшой исторический экскурс в криптографию Postgres.
CREATE TABLE COMPRESSION
Тоже с историей вопроса. Сейчас SET COMPRESSION можно задать как lz4. По умолчанию GUC default_toast_compression = «pglz».
Интересная ситуация с репликацией: при физической репликации можно проигрывать на реплике WALы ведущего сервера, сжатые LZ4, даже если реплика не поддерживает LZ4. Но прочитать данные из таких таблиц не получится: Postgres выдаст ошибку. При логический репликации на каждом сервере всё будет сжато в соответствии с настройками сервера.
С Depesz не просто: уж больно он prolific, так сказать, в своих Waiting for PostgreSQL 14. 18 заметок обозреть не можем, поэтому
Задавайте вопросы
В смысле здесь, а ещё лучше и на докладе Павла ЛузановаPostgreSQL 14. Финальный обзор, который можно будет послушать на PGConf.Russia 2021, которая состоится назло вирусу (но с QR- и экспресс ПЦР-тестами) 25–26-го октября.