Название параметра обещает параллельное применение изменений, поэтому любой, кто наблюдает за отставанием подписчика от издателя, рано или поздно находит его и надеется, что он решит проблему. Но возможности параметра гораздо уже, чем можно предположить.
fillfactor в PostgreSQL управляет тем, насколько заполняются страницы таблицы или индекса. Чем ниже fillfactor, тем выше производительность таблиц, подвергаемых массовым обновлениям. В этой статье мы узнаем все, что необходимо знать о fillfactor в PostgreSQL, начиная с понятия и заканчивая тем, когда именно (и как) вам следует его настраивать.
PostgreSQL обзавёлся множеством фоновых рабочих процессов, в том числе предназначенных для выполнения различных операций параллельно. Сейчас их стало так много, что разобраться во всём этом уже непросто. Давайте наведём порядок.
Ни один из этих параметров не означает того, что можно предположить по его названию.
max_parallel_workers_per_gather задаёт максимальное количество рабочих процессов, которое планировщик может запросить для одного узла плана выполнения. Однако обычно планировщик запрашивает меньше.
Параметр max_parallel_workers в документации описывается как ограничение, действующее для всего кластера. Но фактически оно обеспечивается сравнением общего количества работающих процессов с числом, которое каждый отдельный сеанс устанавливает самостоятельно.
Автор Christophe Pettus: All Your GUCs in a Row: max_parallel_maintenance_workers
max_parallel_maintenance_workers — это верхнее ограничение, до которого в большинстве случаев просто не удаётся добраться: раньше срабатывает какое-нибудь другое ограничение. Параметр задаёт максимальное количество параллельных рабочих процессов, которые может запустить одна служебная команда. Значение по умолчанию — 2, контекст настройки — user, допустимый диапазон — от 0 до 1024. Значение 0 полностью отключает параллельное обслуживание. Увеличить значение параметра несложно. Гораздо труднее добиться того, чтобы команда действительно использовала выделенное ей количество процессов.
max_logical_replication_workers определяет размер пула процессов. В документации перечислены три типа рабочих процессов, использующих этот пул (в PostgreSQL 19 их уже четыре), и на этом объяснение заканчивается. Но упущено самое важное: из всех перечисленных типов только один учитывается при выборе значения параметра, хотя при исчерпании пула ничего не завершается ошибкой. Просто подписка так и не сможет завершить свою работу.
Параметр max_notify_queue_pages никому не был нужен. Он появился потому, что ограничение, которое раньше обеспечивалось само собой, перестало работать, и пришлось придумать ему замену.
max_locks_per_transaction — это ни «на транзакцию», ни «максимум». Это доля на процесс в одной общей для всего кластера таблице блокировок, и любая отдельная транзакция может взять гораздо больше своей доли, пока никто другой не использует свою. Имя вводит людей в заблуждение с 7.2, а описание в документации как «среднего числа объектных блокировок, используемых каждой транзакцией» ближе к истине, хотя вряд ли это то, что вы нанесёте на ручку настройки.
Три функции T-SQL, которые появились за последние несколько релизов, и тихо вышедшие из употребления шаблоны, которые многие из нас до сих пор используют по привычке. Каждая из них заменяет устаревший обходной путь решения задачи одной строкой кода, и в двух из трех случаев выполняется много быстрее. Посмотрите и попробуйте.
1. APPROX_COUNT_DISTINCT - когда COUNT(DISTINCT) слишком дорого обходится
Доступна, начиная с SQL Server 2019. COUNT(DISTINCT col) для столбца с высоким кардинальным числом требует от SQL Server отслеживать каждое уникальное значение, что означает выделение памяти, пропорциональное кардинальному числу, и хеш-агрегат, который любит сбрасываться в базу данных tempdb для больших таблиц. Вместо этого APPROX_COUNT_DISTINCT использует HyperLogLog, который небольшое снижение точности компенсирует значительно меньшим объемом памяти и более быстрой работой.
Продолжить чтение "Три трюка, которые вы, возможно, еще не используете"
max_index_keys считает вещи, которые не являются ключами, начиная с PostgreSQL 11. То, что он сообщает — 32, — это максимальное число столбцов в индексе, а с появлением INCLUDE столбец в индексе не обязательно является ключом: индекс с 31 ключом, несущий один INCLUDE-столбец, находится на пределе, как и индекс с одним ключом, несущий 31 такой столбец. Сообщение об ошибке говорит «столбцов» (cannot use more than 32 columns in an index), pg_controldata говорит Maximum columns in an index:, и только имя параметра всё ещё говорит о ключах.
Вопрос обычно приходит как вопрос безопасности: «Стоит ли использовать параметры привязки, или можно собрать строку SQL самому?» Ответ на этот вопрос таков: используйте параметры привязки, сборка строки — это путь к SQL-инъекции, и все мы можем спокойно жить дальше.
Вопрос производительности, скрывающийся под ним, куда интереснее, и народная мудрость о нём в основном неверна. «Подготовленные операторы пропускают планирование» — обычная версия. Это верно лишь в узком наборе обстоятельств, и когда это верно, это не всегда хорошая новость. Эта статья о том, что PostgreSQL делает с запросом, значения которого впечатаны в текст, что он делает с запросом, значения которого приходят отдельно, и как кэш планов, стоящий между этими двумя путями, принимает свои решения. Есть конкретный момент — шестое выполнение подготовленного оператора, — где два пути расходятся, и удивительно много случаев «мой запрос стал медленным, а я ничего не менял» восходит именно к нему.
max_identifier_length сообщает число 63, и это число — самое неинтересное в нём. Каждая реляционная база данных ограничивает длину имени. Необычно в PostgreSQL то, что происходит, когда вы его превышаете: MySQL, SQL Server и Oracle отвергают оператор, а PostgreSQL обрезает имя до 63 байт, упоминает об этом в NOTICE и продолжает так, будто это то, что вы имели в виду. Почти каждая реальная проблема, связанная с этим параметром, восходит к этому одному решению.
max_files_per_process — это не лимит в том смысле, в каком его понимает большинство людей, когда превышение даёт ошибку. Это размер кэша. Каждый серверный процесс держит пул открытых файловых дескрипторов ядра, и когда пул полон, а серверному процессу нужен ещё один, он закрывает наименее недавно использованный и продолжает. Ничего не ломается. Запрос просто тратит пару дополнительных системных вызовов на файл, который был открыт тридцать секунд назад.
Никто не смотрит max_function_args намеренно. Вы встречаете его, когда PostgreSQL прерывает что-то несвязанное сообщением cannot pass more than 100 arguments to a function, и вы идёте искать ручку. Её нет.