Как стать автором
Обновить
205.95
Postgres Professional
Разработчик СУБД Postgres Pro

PostgreSQL 17: Часть 1 или Коммитфест 2023-07

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров8K


Продолжаем следить за новостями из мира PostgreSQL. Выпуск PostgreSQL 16 Release Candidate 1 планируется на 31 августа и, если всё будет в порядке, то 16-я версия выйдет 14 сентября.


Что изменилось в 16-й версии после апрельской заморозки кода? Что попало в 17 версию по результатам первого коммитфеста? Обо всем об этом в свежем обзоре.


PostgreSQL 16


В начале, для справки, ссылки на предыдущие статьи о 16-й версии, привязанные к коммитфестам: 2022-07, 2022-09, 2022-11, 2023-01, 2023-03.


С апреля произошли некоторые важные изменения, на которые стоит обратить внимание.


И начнем с потерь. Следующие разработки были отменены:



А некоторые работы получили продолжение:


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-й версии по управлению членством в ролях можно прочитать в предыдущих статьях:



Переименование параметра: 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,
    meeting_id integer,
    during tstzrange NOT NULL,
    CONSTRAINT bookings_pk PRIMARY KEY (room, meeting_id)
) 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, meeting_id, during) VALUES
    (1, 1, '[today 13:00,today 16:00)'::tstzrange),
    (11, 1, '[today 13:00,today 16:00)'::tstzrange);

INSERT 0 2

Но нельзя забронировать одну и ту же комнату на пересекающиеся диапазоны времени:


INSERT INTO booking(room, meeting_id, during)
    VALUES (1, 2, '[today 14:00,today 18:00)'::tstzrange);

ERROR:  conflicting key value violates exclusion constraint "booking_1_10_room_during_excl"
DETAIL:  Key (room, during)=(1, ["2023-11-12 14:00:00+03","2023-11-12 18:00:00+03")) conflicts with existing key (room, during)=(1, ["2023-11-12 13:00:00+03","2023-11-12 16:00:00+03")).

[2023.11.12] Для корректной демонстрации работы ограничения-исключения в таблицу добавлен столбец meeting_id. Спасибо nvv за найденную неточность в примере.


Логическая репликация: 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-й версии.

Теги:
Хабы:
Всего голосов 13: ↑13 и ↓0+13
Комментарии0

Публикации

Информация

Сайт
www.postgrespro.ru
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия
Представитель
Иван Панченко