Продолжаем следить за новостями из мира PostgreSQL. Выпуск PostgreSQL 16 Release Candidate 1 планируется на 31 августа и, если всё будет в порядке, то 16-я версия выйдет 14 сентября.
Что изменилось в 16-й версии после апрельской заморозки кода? Что попало в 17 версию по результатам первого коммитфеста? Обо всем об этом в свежем обзоре.
PostgreSQL 16
В начале, для справки, ссылки на предыдущие статьи о 16-й версии, привязанные к коммитфестам: 2022-07, 2022-09, 2022-11, 2023-01, 2023-03.
С апреля произошли некоторые важные изменения, на которые стоит обратить внимание.
И начнем с потерь. Следующие разработки были отменены:
- MAINTAIN ― новая привилегия для обслуживания таблиц (commit: 151c22de)
- Установка параметров на уровне базы данных и пользователя (commit: b9a7a822)
А некоторые работы получили продолжение:
psql: \drg новая команда для просмотра информации о членстве в ролях
commit: d65ddaca
Новая команда добавлена в 16-ю версию уже после заморозки кода. Обычно так не делают, но это лишь доработка интерфейса psql к возможностям сервера, появившимся в 16-й версии.
Создадим роль alice для администрирования ролей:
CREATE ROLE alice LOGIN CREATEROLE;
\c - alice
Пусть при создании ролей alice автоматически наследует привилегии новой роли и возможность переключаться на нее командой SET ROLE:
SET createrole_self_grant = 'INHERIT, SET';
CREATE ROLE bob LOGIN;
Новой командой \drg проверим, что alice включена в роль bob с соответствующими параметрами:
\drg alice
List of role grants
Role name | Member of | Options | Grantor
-----------+-----------+--------------+----------
alice | bob | INHERIT, SET | alice
alice | bob | ADMIN | postgres
(2 rows)
Отмечаем, что роль alice включена в роль bob дважды. Еще одно включение c ADMIN OPTION выполнено от имени начального суперпользователя. Оно и позволяет alice управлять ролью bob. Знать кто именно включил одну роль в другую, важно, т.к. только включивший может выполнить соответствующую команду REVOKE для исключения.
Создадим роль charlie и включим новую роль в bob:
CREATE ROLE charlie LOGIN;
GRANT bob TO charlie WITH ADMIN FALSE, INHERIT FALSE, SET TRUE;
\drg
List of role grants
Role name | Member of | Options | Grantor
-----------+-----------+--------------+----------
alice | bob | INHERIT, SET | alice
alice | bob | ADMIN | postgres
alice | charlie | INHERIT, SET | alice
alice | charlie | ADMIN | postgres
charlie | bob | SET | alice
(5 rows)
В предыдущих версиях членство в ролях проверялось в столбце «Member of» команды \du (или \dg). Но добавить в этот столбец новую информацию о том, кто выдал членство и с какими параметрами, оказалось не просто. Поэтому и была создана новая команда \drg.
А в \du и \dg пришлось убрать столбец «Member of»:
\du
List of roles
Role name | Attributes
-----------+------------------------------------------------------------
alice | Create role
bob |
charlie |
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS
Подробнее о новых возможностях 16-й версии по управлению членством в ролях можно прочитать в предыдущих статьях:
- pg_auth_members: управление предоставлением членства в ролях
- pg_auth_members: членство в ролях и наследование привилегий
- SET ROLE: управление переключением на другую роль
- Роли с атрибутом CREATEROLE
Переименование параметра: io_direct -> debug_io_direct
commit: 319bae9a
Для отладочных целей в 16-й версии появился параметр io_direct. Чтобы название параметра не приводило к желанию его включить, параметр переименовали в debug_io_direct.
Удалены параметры: lc_collate и lc_ctype
commit: b0f6c437
Начиная с 15-й версии для базы данных в качестве провайдера локализации по умолчанию можно использовать библиотеку ICU. Информация о выбранном провайдере и локали сохраняется в столбцах pg_database.datlocprovider и pg_database.daticulocale.
Но, по ряду причин, настройки libc всё равно нужны в каждой базе данных. Поэтому в столбцах pg_database.datcollate и pg_database.datctype по-прежнему есть информация о локали libc, даже если для базы данных выбран провайдер ICU. А параметры lc_collate и lc_ctype всегда показывают именно настройки libc. Получается, что для корректного определения локали базы данных просто посмотреть значение lc_ctype или lc_collate недостаточно. Нужно дополнительно проверить значения столбцов datlocprovider и daticulocale.
Чтобы избежать ошибок в определении локали базы данных, параметры lc_collate и lc_ctype удалили. Информацию о локали следует смотреть в pg_database или командой \list в psql.
Документация: видимые в веб-интерфейсе ссылки на ранее скрытые элементы HTML
commit: e2922702
Некоторые страницы документации в формате HTML содержат якоря для секций или терминов внутри страниц. Например каждый параметр конфигурации в главе «Server Configuration» имеет свой якорь и на него можно ссылаться напрямую. Но как узнать точную ссылку без заглядывания в исходный код страницы?
Начиная с 16 версии в веб-интерфейсе при наведении мыши на название секции или термина, у которого есть ссылка, справа появляется знак # с соответствующей гиперссылкой.
Например, если на странице Client Connection Defaults навести мышь на название search_path, то справа появится знак # с прямой ссылкой на параметр:
https://www.postgresql.org/docs/16/runtime-config-client.html#GUC-SEARCH-PATH
Это очень удобно, когда нужно поделиться точной ссылкой.
Заметим, что на сайте postgrespro.ru подобный функционал давно работает для всех версий русскоязычной документации. Только вместо знака # с правой стороны появляется значок со скрепкой с левой стороны.
PostgreSQL 17
Переходим к 17-й версии. В этот обзор после первого коммитфеста попали следующие изменения:
Прогресс очистки индексов в pg_stat_progress_vacuum
Инкрементальная сортировка для индексов GiST и SP-GiST
Ограничения-исключения с секционированными таблицами
Логическая репликация: REPLICA IDENTITY FULL и hash-индексы
pg_archivecleanup: --clean-backup-history
Новый параметр huge_pages_status
Удален параметр db_user_namespace
События ожидания в расширениях
psql: вывод ECHO_HIDDEN обрамлен строками в виде комментариев
Прогресс очистки индексов в pg_stat_progress_vacuum
commit: 46ebdfe1, f1889729
В представлении pg_stat_progress_vacuum появились два новых столбца: indexes_total и indexes_processed. Первый показывает общее количество индексов для очистки, а второй — сколько индексов уже обработано. Информация обновляется во время выполнения фаз очистки, связанных с индексами: vacuuming indexes и cleaning up indexes.
Это важное улучшение мониторинга очистки больших таблиц с несколькими индексами. Мониторинг через pg_stat_progress_vacuum в таких ситуациях помогал плохо. Ведь благодаря карте видимости, очистка самой таблицы обрабатывает только измененные с предыдущего раза страницы, что при небольших изменениях выполняется достаточно быстро. А вот каждый индекс просматривается полностью, поэтому фазы очистки индексов занимают бóльшую часть времени обработки таблицы и ход выполнения был не виден. Теперь появилась возможность оценивать прогресс очистки по количеству обработанных индексов.
А вот реализовать мониторинг прогресса очистки отдельного индекса не получилось. Процесс сильно отличается для разных типов индексов, к тому же одна и та же страница индекса может обрабатываться несколько раз. Поэтому невозможно корректно реализовать мониторинг, похожий на табличный по схеме количество_очищенных_страниц / общее_количество_страниц.
Инкрементальная сортировка для индексов GiST и SP-GiST
commit: 625d5b3c
Инкрементальная сортировка появилась еще в 13-й версии. Но до сих пор она применялась только с индексами B-дерево. Теперь она работает с индексами GiST и SP-GiST.
Создадим индекс GiST в демонстрационной базе по координатам аэропортов:
CREATE INDEX ON airports_data USING gist (coordinates);
Найдем 10 рейсов из аэропортов, ближайших к заданной точке (для примера с нулевыми координатами), и отсортированные по дате вылета:
EXPLAIN (costs off)
SELECT f.*
FROM flights f
JOIN airports a ON (f.departure_airport=a.airport_code)
ORDER BY point(0,0) <-> a.coordinates, f.scheduled_departure
LIMIT 10;
QUERY PLAN
--------------------------------------------------------------------------------------
Limit
-> Incremental Sort
Sort Key: (('(0,0)'::point <-> ml.coordinates)), f.scheduled_departure
Presorted Key: (('(0,0)'::point <-> ml.coordinates))
-> Nested Loop
Join Filter: (ml.airport_code = f.departure_airport)
-> Index Scan using airports_data_coordinates_idx on airports_data ml
Order By: (coordinates <-> '(0,0)'::point)
-> Materialize
-> Seq Scan on flights f
(10 rows)
Результат запроса нам не интересен, а вот узел Incremental Sort с индексом GiST в плане запроса это то, что и хотелось увидеть.
Ограничения-исключения с секционированными таблицами
commit: 8c852ba9
Для секционированных таблиц появилась возможность создавать ограничения-исключения.
Создадим таблицу бронирования переговорных с секционированием по номеру комнаты:
CREATE TABLE booking(
room integer PRIMARY KEY,
during tstzrange NOT NULL
) PARTITION BY RANGE(room);
CREATE TABLE booking_1_10
PARTITION OF booking FOR VALUES FROM (1) TO (10);
CREATE TABLE booking_11_20
PARTITION OF booking FOR VALUES FROM (11) TO (20);
Чтобы нельзя было дважды забронировать одну и ту же комнату, добавим ограничение-исключение. Как и первичный ключ таблицы, это ограничение обязано включать столбцы ключа секционирования, и только с оператором равенства:
CREATE EXTENSION btree_gist;
ALTER TABLE booking ADD CONSTRAINT no_intersect
EXCLUDE USING gist(room WITH =, during WITH &&);
Разные комнаты из разных секций можно бронировать на одно и тоже время:
INSERT INTO booking(room, during) VALUES
(1, '[today 13:00,today 16:00)'::tstzrange),
(11, '[today 13:00,today 16:00)'::tstzrange);
INSERT 0 2
Но нельзя забронировать одну и ту же комнату на пересекающиеся диапазоны времени:
INSERT INTO booking(room, during)
VALUES (1, '[today 14:00,today 18:00)'::tstzrange);
ERROR: duplicate key value violates unique constraint "booking_1_10_pkey"
DETAIL: Key (room)=(1) already exists.
Логическая репликация: REPLICA IDENTITY FULL и hash-индексы
commit: edca3424
Возможность использовать неуникальный индекс для идентификации измененных строк на подписчике появилась в 16-й версии. Но только для индексов типа B-дерево. В 17-й версии могут использоваться и индексы типа hash.
pg_archivecleanup: --clean-backup-history
commit: dd7c60f1, 4a7556f7, 3f8c98d0
Первый коммит добавляет возможность указывать длинные имена параметров, второй коммит выполняет рефакторинг существующего кода, и только третий осуществляет первоначальную задумку, а именно добавляет новый параметр --clean-backup-history. Параметр предназначен для удаления старых файлов истории резервных копий. Раньше эти файлы небольшого размера всегда оставались для отладочных целей.
Новый параметр huge_pages_status
commit: a14354ca
Новый параметр huge_pages_status показывает статус использования огромных страниц:
\dconfig huge*
List of configuration parameters
Parameter | Value
-------------------+-------
huge_pages | try
huge_page_size | 2MB
huge_pages_status | off
(3 rows)
В данном случае значение параметра подсказывает, что при запуске сервер не смог выделить память под огромные страницы.
Удален параметр db_user_namespace
commit: 884eee5b
Параметр позволял относить имена пользователей к базам данных. 21 год назад эта функциональность была заявлена в качестве временной меры, но, похоже, так и не была востребована.
События ожидания в расширениях
commit: c9af0546
Разработчики расширений получили возможность определять собственные события ожидания. Сейчас все расширения используют один тип событий ожидания: Extension. Но если установлено несколько расширений, то из pg_stat_activity сложно понять, в каком именно расширении произошла задержка.
Пока реализован интерфейс для создания расширениями событий ожидания. В дальнейшем предполагается доработать существующие расширения contrib для уточнения имени события ожидания.
psql: вывод ECHO_HIDDEN обрамлен строками в виде комментариев
commit: 19c590f6
Включение ECHO_HIDDEN в командной строке или одноименной переменной приводит к выводу запросов SQL, используемых в командах psql:
$ psql --echo-hidden -c '\db';
/******** QUERY *********/
SELECT spcname AS "Name",
pg_catalog.pg_get_userbyid(spcowner) AS "Owner",
pg_catalog.pg_tablespace_location(oid) AS "Location"
FROM pg_catalog.pg_tablespace
ORDER BY 1;
/************************/
List of tablespaces
Name | Owner | Location
------------+----------+----------
pg_default | postgres |
pg_global | postgres |
(2 rows)
Окружающие запрос строки оформлены как комментарии, что удобно для последующего использования в скриптах или копировании в редактор. В предыдущих версиях строки начинались и заканчивались звездочками.
Такие же изменения сделаны для параметров --log-file и --single-step.
На этом всё. Ждем выхода PostgreSQL 16 и сентябрьского коммитфеста 17-й версии.