- PVSM.RU - https://www.pvsm.ru -
Август в релизном цикле PostgreSQL месяц особенный. Еще не вышла официально 15-я версия, но уже закончился первый коммитфест [1] 16-й версии. И мы можем посмотреть на самые интересные изменения.
Собираем сервер из исходного кода [2] и вперед!
dconfig server_version
List of configuration parameters
Parameter | Value
----------------+---------
server_version | 16devel
После заморозки кода 15-й версии не обошлось без потерь. Откатили:
Индексы BRIN не блокируют HOT-обновления [3]
Оптимизация работы с вложенными транзакциями [4]
В этот обзор попали 14 изменений:
psql: pset xheader_width [5]
vacuumdb --schema и --exclude-schema [6]
Новые возможности утилиты createuser [7]
Сообщение журнала о контрольной точке дополнили номерами LSN самой точки и начала восстановления [8]
pg_prepared_statements.result_types [9]
auto_explain: параметр log_parameter_max_length [10]
Необязательные псевдонимы для подзапросов во фразе FROM [11]
REINDEX: синтаксис и не только [12]
CREATE STATISTICS: необязательно указывать имя статистики [13]
CREATE TABLE: атрибут STORAGE [14]
У созданного при инициализации кластера пользователя нельзя отобрать полномочия суперпользователя [15]
Триггеры на TRUNCATE для внешних таблиц [16]
pg_read_file/pg_read_binary_file: новая вариация указания параметров [17]
Собственные менеджеры ресурсов WAL [18]
psql: pset xheader_width [19]
commit: a45388d6 [20]
Развернутый режим вывода результатов запросов (x или pset expanded) удобен когда данные всех столбцов не помещаются на экран. Но и в развернутом режиме данные длинных столбцов также могут не помещаться в окно терминала.
Для примера в окне терминала шириной в 72 символа выполним запрос:
pset expanded on
pset pager off
SELECT version(),
length(version()) version_length;
-[ RECORD 1 ]--+--------------------------------------------------------
-------------------------------------------------
version | PostgreSQL 16devel on x86_64-pc-linux-gnu, compiled by
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
version_length | 104
Значение функции version не помещается по ширине, поэтому переносится на следующую строку. С этим все нормально. Но вот строка заголовка записи форматируется по самому широкому столбцу и также переносится на следующую строку. И чем длиннее самый широкий столбец, тем больше места будет занимать строка заголовка записи. Это особенно неудобно, когда выводится несколько записей и у каждой записи заголовок занимает несколько строк. (Попробуйте выполнить в развернутом режиме запрос SELECT * FROM pg_proc;
)
В 16-й версии в psql появился новый параметр форматирования строки заголовка развернутого режима.
pset xheader_width
Expanded header width is 'full'.
Значение по умолчанию (full) соответствует поведению в предыдущих версиях. Другие возможные значения:
pset xheader_width column
Expanded header width is 'column'.
SELECT version(),
length(version()) version_length;
-[ RECORD 1 ]--+
version | PostgreSQL 16devel on x86_64-pc-linux-gnu, compiled by
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
version_length | 104
Заголовок записи больше не расходует напрасно полезное место окна терминала.
vacuumdb --schema и --exclude-schema [21]
commit: 7781f4e3 [22]
У vacuumdb новые параметры для очистки таблиц в указанных схемах (--schema) или таблиц, не принадлежащих указанным схемам (--exclude-schema).
Новые возможности утилиты createuser [23]
commit: 08951a7c [24]
Утилита createuser является оберткой над командой CREATE ROLE, но с ограниченным функционалом. Это изменение добавляет утилите ряд параметров, реализующих отсутствующие ранее возможности, а именно:
Сообщение журнала о контрольной точке дополнили номерами LSN самой точки и начала восстановления [25]
commit: 62c46eee [26]
После завершения контрольной точки в WAL делается запись с номером LSN контрольной точки и номером LSN, откуда начинать восстановление в случае сбоя (redo LSN).
Для последней выполненной контрольной точки эти два номера LSN записываются в управляющий файл:
$ pg_controldata | egrep 'Latest.*location'
Latest checkpoint location: 1/1A3DEB20
Latest checkpoint's REDO location: 1/1A3DEAE8
А в 16-й версии их добавили в сообщение о завершении контрольной точки журнала сервера:
2022-08-02 12:15:17.961 MSK [198868] LOG: checkpoint complete: wrote 0 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.001 s, sync=0.001 s, total=0.072 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=418462 kB; lsn=1/1A3DEB20, redo lsn=1/1A3DEAE8
Стоит напомнить, что начиная с 15-й версии параметр log_checkpoints включен по умолчанию.
pg_prepared_statements.result_types [27]
commit: 84ad713c [28], 6ffff0fd [29]
В представление pg_prepared_statements добавили столбец result_types.
PREPARE get_booking (text) AS
SELECT * FROM bookings WHERE book_ref = $1;
SELECT * FROM pg_prepared_statements WHERE name = 'get_booking'gx
-[ RECORD 1 ]---+-----------------------------------------------
name | get_booking
statement | PREPARE get_booking (text) AS +
| SELECT * FROM bookings WHERE book_ref = $1;
prepare_time | 2022-08-02 16:54:14.313221+03
parameter_types | {text}
result_types | {character,"timestamp with time zone",numeric}
from_sql | t
generic_plans | 0
custom_plans | 0
Для подготовленных операторов без возвращаемого значения, столбец будет оставаться пустым.
auto_explain: параметр log_parameter_max_length [30]
commit: d4bfe412 [31]
Новый параметр расширения auto_explain.log_parameter_max_length выполняет ту же задачу, что и аналогичный log_parameter_max_length, а именно ― журналирует значения параметров запросов.
LOAD 'auto_explain';
SHOW auto_explain.log_parameter_max_length;
auto_explain.log_parameter_max_length
---------------------------------------
-1
(1 row)
Значение по умолчанию равно -1. Это говорит о том, что будут выводиться полные значения параметров. Значение 0 отключает вывод значений параметров, положительное число ограничивает вывод значений указанным количеством байт.
Настроим журналирование и сформируем параметризированный запрос командой EXECUTE… USING в анонимном блоке PL/pgSQL.
SET auto_explain.log_min_duration = 0;
SET auto_explain.log_nested_statements = 'on';
SET auto_explain.log_level = 'NOTICE';
DO $$BEGIN EXECUTE 'SELECT $1' USING 42; END;$$;
NOTICE: duration: 0.003 ms plan:
Query Text: SELECT $1
Query Parameters: $1 = '42'
Result (cost=0.00..0.01 rows=1 width=4)
DO
В вывод добавилась строка Query Parameters, позволяющая узнать, с какими значениями выполнялся запрос в строке Query Text.
Необязательные псевдонимы для подзапросов во фразе FROM [32]
commit: bcedd8f5 [33]
Для подзапросов во фразе FROM стандарт SQL требует наличия псевдонима:
15=# SELECT * FROM (SELECT 42 AS a);
ERROR: subquery in FROM must have an alias
LINE 1: SELECT * FROM (SELECT 42 AS a);
^
HINT: For example, FROM (SELECT ...) [AS] foo.
Однако это осложняет миграцию с других СУБД, где наличие псевдонима необязательно.
В 16-й версии такие псевдонимы не обязательны и в PostgreSQL.
16=# SELECT * FROM (SELECT 42 AS a);
a
----
42
(1 row)
REINDEX: синтаксис и не только [34]
commit: 2cbc3c17 [35]
Варианты команды REINDEX DATABASE и REINDEX SYSTEM требовали указания базы данных. Но указать можно только текущую базу данных, что делает это требование излишним. В новой версии имя базы данных становится необязательным.
Кроме того, команда REINDEX DATABASE теперь переиндексирует только пользовательские индексы и пропускает индексы таблиц системного каталога. Прежнего поведения, а именно перестроения всех индексов базы данных, можно добиться выполнением двух команд REINDEX DATABASE и REINDEX SYSTEM.
Такое изменение обосновано тем, что до сих пор не было способа перестроить только пользовательские индексы во всей базе данных. К тому же перестроение системных индексов невозможно в режиме CONCURRENTLY, а в высоконагруженных системах может вызывать взаимоблокировки.
CREATE STATISTICS: необязательно указывать имя статистики [36]
commit: 624aa2a1 [37]
Расширенная статистика ― отдельный объект в базе данных и нуждается в имени. Но почему бы не разрешить опускать имя при создании, доверив его формирование самой СУБД? Точно так же, как это возможно для индексов и ограничений целостности.
Сделали:
CREATE STATISTICS ON departure_airport, arrival_airport FROM flights;
d flights
...
Statistics objects:
"bookings.flights_departure_airport_arrival_airport_stat" ON departure_airport, arrival_airport FROM flights
CREATE TABLE: атрибут STORAGE [38]
commit: 784cedda [39]
Предположим, мы решили хранить изображения в базе данных. Создаем таблицу:
CREATE TABLE images (filename text, data bytea);
ALTER TABLE images ALTER COLUMN data SET STORAGE external;
Во второй команде меняем стратегию хранения TOAST на external, чтобы запретить сжатие данных. Ведь файлы изображений и так сжаты.
Вопрос в том, зачем это делать отдельной командой, а не сразу указать нужную стратегию в CREATE TABLE? Ответ простой: CREATE TABLE до 16-й версии не позволяет указывать атрибут STORAGE для столбцов, что и было исправлено:
CREATE TABLE images (filename text, data bytea STORAGE external);
У созданного при инициализации кластера пользователя нельзя отобрать полномочия суперпользователя [40]
commit: e530be2c [41]
Суперпользователь, созданный при инициализации кластера (pg_authid.oid=10), мог сам у себя отобрать атрибут SUPERUSER:
15=# ALTER ROLE postgres NOSUPERUSER;
(Если другого суперпользователя нет, то чтобы вернуть атрибут придется запускать сервер в однопользовательском режиме.)
В 16-й версии случайно лишиться суперпользовательских полномочий не получится:
16=# ALTER ROLE postgres NOSUPERUSER;
ERROR: permission denied: bootstrap user must be superuser
Кстати, удалить суперпользователя, созданного при инициализации кластера было и раньше нельзя:
CREATE ROLE root LOGIN SUPERUSER;
c - root
DROP ROLE postgres;
ERROR: cannot drop role postgres because it is required by the database system
Общий вывод можно сделать такой. Начальный суперпользователь необходим для нормального функционирования сервера. Удалять или отнимать у него привилегии не нужно. В плане обеспечения дополнительной безопасности можно подумать [42] о том, чтобы сделать эту роль групповой, забрав атрибут LOGIN.
Триггеры на TRUNCATE для внешних таблиц [43]
commit: 3b00a944 [44]
Некоторые обертки сторонних данных поддерживают команду TRUNCATE. Этот патч добавляет возможность создавать триггер на TRUNCATE для внешних таблиц таких оберток.
pg_read_file/pg_read_binary_file: новая вариация указания параметров [45]
commit: 283129e3 [46]
Спецификация функций pg_read_file и похожей pg_read_binary_file была такой:
pg_read_file ( filename text [, offset bigint, length bigint [, missing_ok boolean ]] ) → text
Предполагается, что для чтения файла целиком нужно не указывать параметры offset и length. Но тогда не получается задать missing_ok=true для игнорирования отсутствия файла.
В 16-й версии добавили еще один перегруженный вариант функций, что привело общую спецификацию к виду:
pg_read_file ( filename text [, offset bigint, length bigint ] [, missing_ok boolean ] ) → text
Теперь можно указать только имя файла и игнорировать его отсутствие.
Собственные менеджеры ресурсов WAL [47]
commit: 5c279a6d [48]
Особую роль патча подчеркивает мой коллега, Егор Рогов. Ему и слово.
Одна из проблем, стоящих перед разработчиками табличных и индексных методов доступа — невозможность формировать журнальные записи специфического вида. Существует механизм унифицированных журнальных записей [49], который сбрасывает в WAL “разницу” между старым и новым состояниями страницы (им пользуется, например, расширение rum [50]), но он не слишком эффективен и не поддерживает логическую репликацию.
В версии 16 расширения смогут создавать собственные менеджеры ресурсов [51] и, соответственно, журнальные записи собственного формата. Обратная сторона медали в том, что восстановление экземпляра после сбоя становится зависимым от стороннего расширения.
С точки зрения пользователя патч ничего не меняет, но это еще один важный шаг на пути к появлению новых методов доступа.
На этом пока всё. Ждем следующего сентябрьского коммитфеста [52] и, конечно же, официального выхода 15-й версии.
Автор: Павел Лузанов
Источник [53]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/postgresql/377710
Ссылки в тексте:
[1] первый коммитфест: https://commitfest.postgresql.org/38/
[2] исходного кода: https://git.postgresql.org/gitweb/?p=postgresql.git;a=summary
[3] Индексы BRIN не блокируют HOT-обновления: https://habr.com/ru/company/postgrespro/blog/596567#commit_e3fcca0d
[4] Оптимизация работы с вложенными транзакциями: https://habr.com/ru/company/postgrespro/blog/679264/#commit_06f5295a
[5] psql: pset xheader_width: #commit_a45388d6
[6] vacuumdb --schema и --exclude-schema: #commit_7781f4e3
[7] Новые возможности утилиты createuser: #commit_08951a7c
[8] Сообщение журнала о контрольной точке дополнили номерами LSN самой точки и начала восстановления: #commit_62c46eee
[9] pg_prepared_statements.result_types: #commit_84ad713c
[10] auto_explain: параметр log_parameter_max_length: #commit_d4bfe412
[11] Необязательные псевдонимы для подзапросов во фразе FROM: #commit_bcedd8f5
[12] REINDEX: синтаксис и не только: #commit_2cbc3c17
[13] CREATE STATISTICS: необязательно указывать имя статистики: #commit_624aa2a1
[14] CREATE TABLE: атрибут STORAGE: #commit_784cedda
[15] У созданного при инициализации кластера пользователя нельзя отобрать полномочия суперпользователя: #commit_e530be2c
[16] Триггеры на TRUNCATE для внешних таблиц: #commit_3b00a944
[17] pg_read_file/pg_read_binary_file: новая вариация указания параметров: #commit_283129e3
[18] Собственные менеджеры ресурсов WAL: #commit_5c279a6d
[19] psql: pset xheader_width: https://commitfest.postgresql.org/38/3295/
[20] a45388d6: https://github.com/postgres/postgres/commit/a45388d6
[21] vacuumdb --schema и --exclude-schema: https://commitfest.postgresql.org/38/3612/
[22] 7781f4e3: https://github.com/postgres/postgres/commit/7781f4e3
[23] Новые возможности утилиты createuser: https://commitfest.postgresql.org/38/3618/
[24] 08951a7c: https://github.com/postgres/postgres/commit/08951a7c
[25] Сообщение журнала о контрольной точке дополнили номерами LSN самой точки и начала восстановления: https://commitfest.postgresql.org/38/3474/
[26] 62c46eee: https://github.com/postgres/postgres/commit/62c46eee
[27] pg_prepared_statements.result_types: https://commitfest.postgresql.org/38/3644/
[28] 84ad713c: https://github.com/postgres/postgres/commit/84ad713c
[29] 6ffff0fd: https://github.com/postgres/postgres/commit/6ffff0fd
[30] auto_explain: параметр log_parameter_max_length: https://commitfest.postgresql.org/38/3660/
[31] d4bfe412: https://github.com/postgres/postgres/commit/d4bfe412
[32] Необязательные псевдонимы для подзапросов во фразе FROM: https://commitfest.postgresql.org/38/3714/
[33] bcedd8f5: https://github.com/postgres/postgres/commit/bcedd8f5
[34] REINDEX: синтаксис и не только: https://commitfest.postgresql.org/38/3636/
[35] 2cbc3c17: https://github.com/postgres/postgres/commit/2cbc3c17
[36] CREATE STATISTICS: необязательно указывать имя статистики: https://commitfest.postgresql.org/38/3708/
[37] 624aa2a1: https://github.com/postgres/postgres/commit/624aa2a1
[38] CREATE TABLE: атрибут STORAGE: https://commitfest.postgresql.org/38/3479/
[39] 784cedda: https://github.com/postgres/postgres/commit/784cedda
[40] У созданного при инициализации кластера пользователя нельзя отобрать полномочия суперпользователя: https://www.postgresql.org/message-id/flat/CA%2BTgmoZirCwArJms_fgvLBFrC6b%3DHdxmG7iAhv%2Bkt_%3DNBA7tEw%40mail.gmail.com
[41] e530be2c: https://github.com/postgres/postgres/commit/e530be2c
[42] подумать: https://www.postgresql.org/message-id/f941fa4a-a294-165a-82c4-947d3c8425f6%40joeconway.com
[43] Триггеры на TRUNCATE для внешних таблиц: https://www.postgresql.org/message-id/flat/20220630193848.5b02e0d6076b86617a915682%40sraoss.co.jp
[44] 3b00a944: https://github.com/postgres/postgres/commit/3b00a944
[45] pg_read_file/pg_read_binary_file: новая вариация указания параметров: https://commitfest.postgresql.org/38/3730/
[46] 283129e3: https://github.com/postgres/postgres/commit/283129e3
[47] Собственные менеджеры ресурсов WAL: https://commitfest.postgresql.org/38/3469/
[48] 5c279a6d: https://github.com/postgres/postgres/commit/5c279a6d
[49] унифицированных журнальных записей: https://postgrespro.ru/docs/postgresql/14/generic-wal
[50] rum: https://github.com/postgrespro/rum
[51] собственные менеджеры ресурсов: https://www.postgresql.org/docs/15/custom-rmgr.html
[52] сентябрьского коммитфеста: https://commitfest.postgresql.org/39/
[53] Источник: https://habr.com/ru/post/681164/?utm_source=habrahabr&utm_medium=rss&utm_campaign=681164
Нажмите здесь для печати.