PostgreSQL 15: Часть 3 или Коммитфест 2021-11
Вместе с началом зимы, релизный цикл 15-й версии продвинулся еще на один, теперь уже третий, коммитфест. Напомню, что о предыдущих двух можно подробнее прочитать здесь: 2021–07, 2021–09.
Теперь же посмотрим, что происходило в последнем на текущий момент, ноябрьском коммитфесте.
Мониторинг
Журналирование работы процесса startup
commit: 9ce346ea
При запуске сервера основное время обычно уходит на синхронизацию каталога данных с диском (fsync), удаление нежурналируемых таблиц и применение файлов WAL.
Если сервер долго не запускается, хочется знать чем именно занимается процесс startup, не завис ли он. Ответ на этот вопрос теперь можно увидеть в журнале сервера, куда будет записываться текущий статус работы процесса startup. Частота записи сообщений настраивается новым параметром log_startup_progress_interval, по умолчанию раз в 10 секунд.
На репликах, где процесс startup работает постоянно и накатывает изменения, информация о применении файлов WAL записываться не будет, чтобы не засорять журнал.
Новые события ожидания для команд управления файловым архивом WAL
commit: 1b06d7ba
Пополнение в списке событий ожидания, относящихся к типу IPC: ArchiveCommand, ArchiveCleanupCommand, RestoreCommand, RecoveryEndCommand.
Каждое из ожиданий устанавливается на время выполнения команды shell соответствующего параметра конфигурации.
Функции для просмотра содержимого каталогов логической репликации
commit: 1922d7c6
Для мониторинга работы логической репликации могут пригодиться новые функции для просмотра соответствующих каталогов файловой системы:
Производительность
Сортировка данных: замена многофазного слияния на многопутевое сбалансированное слияние
commit: 65014000
Очередная оптимизация алгоритмов сортировки. В частности речь идет о внешней сортировке, представленной в планах запросов как «Sort Method: external merge».
Улучшения не очень значительные, но почитатели Кнута могут включить trace_sort и исследовать изменения, особенно на небольших значениях work_mem.
Индексы BRIN не блокируют HOT-обновления
commit: 5753d4ee
HOT-обновление не применяется, если хотя бы один изменяемый столбец команды UPDATE проиндексирован любым типом индекса.
Однако индексы BRIN не содержат ссылок на табличные строки. И использовать HOT для обновления столбцов с такими индексами вполне безопасно. Поэтому в 15-й версии индексы BRIN больше не будут препятствовать оптимизации HOT update:
15=# CREATE INDEX flights_bi ON flights USING brin(actual_departure);
15=# SELECT pg_stat_reset_single_table_counters('flights'::regclass);
15=# UPDATE flights SET actual_departure = actual_departure + '5 min'::interval
WHERE flight_id = 1;
15=# SELECT n_tup_hot_upd FROM pg_stat_all_tables WHERE relname = 'flights';
n_tup_hot_upd
---------------
1
Процесс archiver и файлы в pg_wal/archive_status
commit: beb4e9ba
До определенных ситуаций дело лучше не доводить. Например, если команда из archive_command по каким-то причинам уже давно перестала копировать файлы в архив, а места в pg_wal хоть отбавляй.
Последствия будут такими: в каталоге pg_wal и, в частности, в pg_wal/archive_status накопится огромное количество файлов. При каждом запуске процесс archiver должен просканировать archive_status в поисках файла для архивирования, что может занять очень и очень много времени, хотя сама команда archive_command выполняется быстро. По сути, в такой ситуации процесс архивирования практически парализован.
Чтобы было немного полегче, процесс archiver будет запоминать сразу несколько файлов для архивирования, чтобы не сканировать каталог archive_status при каждом запуске. Но всё-таки до такой ситуации лучше просто не доводить.
Узел Gather: оптимизация пересылки строк от рабочих процессов
commit: 46846433
В параллельных запросах узел Gather теперь получает строки от рабочих процессов с меньшими затратами.
Разработчики серьезно подумывают над уменьшением parallel_tuple_cost, чтобы в новых реалиях планы с параллельным выполнением выбирались чаще.
starts_with и ^@: добавлена вспомогательная функция для планировщика
commit: a148f8bc
То, как выполняются функции зачастую является «черным ящиком» для СУБД. Но у разработчиков есть возможность рассказать о них планировщику при помощи вспомогательных функций.
Такая вспомогательная функция была добавлена для функции starts_with и связанного с ней оператора ^@.
Увидеть изменения можно на оценке кардинальности простого запроса. Посмотрим, как часто имя Павел встречается в билетах.
14=# SELECT count(*) FROM tickets WHERE starts_with(passenger_name,'PAVEL');
count
-------
24090
А теперь что думает по этому поводу планировщик в 14-й версии:
14=# EXPLAIN SELECT * FROM tickets WHERE starts_with(passenger_name,'PAVEL');
QUERY PLAN
------------------------------------------------------------------
Seq Scan on tickets (cost=0.00..86286.54 rows=983241 width=104)
...
Как видно, оценка сильно неточная. А теперь в 15-й версии:
15=# EXPLAIN SELECT * FROM tickets WHERE starts_with(passenger_name,'PAVEL');
QUERY PLAN
--------------------------------------------------------------------------------
Gather (cost=1000.00..68502.23 rows=27236 width=104)
...
Почти идеально.
Дополнительный бонус для тех кто использует правило сортировки C. Функция starts_with, как и оператор ^@, смогут использовать не только индексы SP-GiST, но и Btree.
Процедурные языки
PL/pgSQL: локализация ошибок в секции инициализации
commit: acb2d7d5
Выполняем анонимный блок PL/pgSQL:
14=# DO $$DECLARE
x int := 42;
y int := 1/0;
z text := 'Hello';
BEGIN
END; $$;
ERROR: division by zero
CONTEXT: SQL expression "1/0"
PL/pgSQL function inline_code_block line 5 during statement block local variable initialization
Понятно, что делить на 0 нельзя, но почему ошибка в 5-й строке?
А все потому, что любая ошибка в секции DECLARE помечается той строкой, где расположено слово BEGIN. И не важно при инициализации какой переменной произойдет ошибка, всё равно в сообщении строка останется пятой.
Откровенно говоря, неудобно. Было. А теперь:
15=# DO $$DECLARE
x int := 42;
y int := 1/0;
z text := 'Hello';
BEGIN
END; $$;
ERROR: division by zero
CONTEXT: SQL expression "1/0"
PL/pgSQL function inline_code_block line 3 during statement block local variable initialization
Репликация
Логическая репликация всех таблиц схемы
commit: 5a283246
Задать список таблиц при создании публикации можно двумя способами. Либо явно перечислить, либо указать FOR ALL TABLES. Во втором случае в публикацию включаются все таблицы базы данных.
Но что если нужно реплицировать все таблицы определенных схем, но не всей базы данных? В 15-й версии это просто:
CREATE PUBLICATION bookings_pub FOR ALL TABLES IN SCHEMA bookings;
Теперь в другой базе данных, при наличии схемы bookings и всех её таблиц, можно подписываться на публикацию.
Новая таблица в схеме bookings автоматически добавится в публикацию. Правда на стороне подписки чуда не произойдет. Логическая репликация пока не умеет передавать команды DDL. Поэтому в базе данных подписчика придется создать таблицу и обновить подписку (ALTER SUBSCRIPTION… REFRESH PUBLICATION).
Описание от depesz.
pg_receivewal: поддержка lz4
commit: babbbb59, d62bcc8b
Утилита pg_receivewal, в дополнение к gzip, теперь поддерживает метод сжатия lz4 (если PostgreSQL был скомпилирован с параметром --with-lz4). Для выбора метода сжатия предназначен новый параметр утилиты pg_receivewal --compression-method.
Безопасность
Все три нововведения в этой группе относятся к теме администрирования сервера без использования полномочий суперпользователя.
Права доступа к pg_backend_memory_contexts и pg_shmem_allocations
commit: 77ea4f94
Предопределенная роль pg_read_all_stats получила доступ к представлениям pg_backend_memory_contexts и pg_shmem_allocations, а также к функциям, на основе которых эти представления созданы.
Права доступа к pg_log_backend_memory_contexts
commit: f0b051e3
С функции pg_log_backend_memory_contexts снята проверка на работу только под суперпользователем. Теперь суперпользователь может выдать права на выполнение этой функции любой роли.
Права доступа к CHECKPOINT
commit: 4168a474
Новая предопределенная роль pg_checkpointer дает право выполнить команду CHECKPOINT.
Разное
amcheck: проверки для TOAST
commit: bd807be6
В модуле amcheck новые проверки. Теперь перенесенные в TOAST значения проверяются на корректный размер и способ компрессии.
Новая реализация random
commit: 3804539e
Заменен, используемый функцией random, устаревший алгоритм генерации псевдо-случайных чисел на современный Xoroshiro128+. У нового алгоритма лучше статистические свойства, а реализация меньше зависит от платформы.
btree_gist: поддержка типа bool
commit: 57e3c516, e2fbb883
В длинный список поддерживаемых модулем btree_gist типов данных добавлен логический тип.
На этом пока всё. Продолжение следует после январского коммитфеста.