Ваша база данных работает как часы — пока простой DELETE не поставит её на колени. Что пошло не так? Хотя мы склонны сосредотачиваться на оптимизации операций SELECT и INSERT, мы часто упускаем из виду скрытую сложность DELETE. А ведь удаление ненужных данных столь же важно. Устаревшие или нерелевантные данные могут раздувать вашу базу данных, снижать производительность и делать обслуживание кошмаром. Хуже того, хранение некоторых типов данных без действительного обоснования может даже привести к проблемам соответствия.
maintenance_io_concurrency — это effective_io_concurrency для работы, которую документация описывает как выполняемую «от имени множества клиентских сеансов». Эта фраза — весь смысл дизайна: VACUUM выплачивает долг по вводу-выводу, который накопил каждый сеанс, поэтому он может разумно быть более агрессивным в упреждающем чтении, чем любой из них. Механически эти два параметра — одна и та же ручка, включая трёхэтапную историю того, что означает число, и я не буду повторять это здесь. Эта статья о том, какая работа управляется им, потому что список не таков, как подсказывает название.
logical_decoding_work_mem — это то, сколько чужой незафиксированной транзакции walsender будет держать в памяти, прежде чем начнёт записывать эту транзакцию на диск во второй раз.
"SQL Server медленный". Как часто вы слышали это? Наиболее часто недовольство возникает при проблемах с производительностью, но во многих случаях это утверждение не выдерживает анализа. Чаще всего SQL Server просто реагирует на возлагаемую на него рабочую нагрузку, и сама рабочая нагрузка является проблемой.
SQL Server не гадает. Он точно показывает, где он потратил время и почему. Если проблема в движке, данные это покажут. Если нет, он покажет это так же ясно. Цель состоит в отделении догадок от фактов и проверки, действительно ли узкое место находится в SQL Server, а не в слое приложения.
Начнем со статистики ожиданий
Первый шагом является проверка статистики ожидания, которая дает непосредственный взгляд на то, где SQL Server проводит время в ожидании. Если имеется узкое место во вводе-выводе, блокировке или записи в журнал транзакций, это будет отражено в ожиданиях.
Продолжить чтение "Когда SQL Server не является узким местом"
Это самые старые параметры журналирования, которые PostgreSQL всё ещё поставляет, и вывод выглядит соответственно. Каждый из них — булев параметр, по умолчанию выключен, контекст superuser, и каждый заставляет серверный процесс вызывать getrusage() до и после одной стадии выполнения оператора и записывать разницу в журнал на уровне LOG. log_parser_stats покрывает парсер, анализ разбора и переписчик (три блока на оператор, по одному на стадию); log_planner_stats покрывает планировщик; log_executor_stats покрывает исполнитель; а log_statement_stats покрывает весь оператор, поэтому он отказывается включаться вместе с любым из других трёх, и они отказываются включаться вместе с ним. Вывод для одного SELECT count(*) при включённом log_statement_stats:
log_lock_waits — самый дешёвый детектор конкуренции за блокировки, который поставляет PostgreSQL, и вплоть до версии 18 он по умолчанию выключен. Включите его. PostgreSQL 19 сделает это за вас.
Эти два параметра отвечают на один и тот же вопрос об одном и том же процессе: что делает процесс запуска и почему он ещё не закончил? Процесс запуска — это серверный процесс, который воспроизводит WAL. На первичном сервере он существует только во время восстановления после сбоя, и пока он существует, ничто другое не может подключиться; клиент получает FATAL: the database system is not yet accepting connections. Когда он завершается, он выходит, и postmaster открывает двери. На standby он никогда не завершается; он воспроизводит в течение всей жизни сервера, и вопрос там не в том, как далеко он продвинулся, а в том, почему он остановился. Один параметр — для каждой из ситуаций, и оба отвечают в журнале сервера, потому что в обеих ситуациях журнал — единственное место, куда можно посмотреть.
По-настоящему полезный параметр, о котором почти никто не знает. Добавлен в PostgreSQL 14, по умолчанию выключен, исправляет конкретную патологию, которую каждый, кто запускал аналитические нагрузки, пережил хотя бы раз.
В прошлый раз мы закончили на log_min_duration_statement, установленном на порог, который вы действительно стали бы расследовать. Цена этого порога в том, что всё ниже него невидимо, а запросы ниже него часто и есть суть истории: один запрос, выполняющийся минуту, — это проблема, которую вы видите, но двадцать миллионов запросов по миллисекунде каждый — это пять с половиной часов времени базы данных, которые никогда не породят ни одной строки журнала. pg_stat_statements показывает вам этот агрегат. Чего он не может показать — так это реальный экземпляр: настоящее выполнение, с его настоящими значениями параметров, в его настоящий момент. Вот что покупают эти три параметра, при объёме журнала, который вы выбираете заранее.
Все остальные параметры журналирования операторов в этом семействе решают, попадёт ли запрос в журнал. Эти два решают, попадут ли туда данные ваших пользователей.
Многие годы pgBackRest был одним из наиболее пользующихся доверием решений для резервирования в экосистеме PostgreSQL. Он обеспечивал бесчисленные производственные системы, спокойно обеспечивая возможность восстановления и устойчивость к неожиданным сбоям.
Но в 2026 году кое-что радикально поменялось.
Конец pgBackRest (каким мы его знаем)
Мейнтейнер pgBackRest официально объявил, что проект больше не поддерживается спустя более десятилетия его разработки.
Каждое сообщение на пути к серверному журналу проходит через трое ворот: попадает ли оно туда вообще, едет ли вместе с ним SQL, который его вызвал, и сколько его полей будет напечатано. По одному параметру на каждые ворота. Все три управляют только копией сообщения в журнале; то, что видит клиент, — дело client_min_messages, и эти два потока фильтруются независимо. Все три имеют контекст superuser: их можно устанавливать на лету в сеансе, но только суперпользователем или ролью, которой предоставлено право SET на параметр (15 и новее), и суперпользователь может ограничить их область с помощью ALTER ROLE ... SET или ALTER DATABASE ... SET. Обычная роль входа подхватывает ALTER ROLE ... SET log_min_messages во время подключения, даже если она не может установить параметр сама; я проверил.
Строка журнала состоит из двух частей: сообщение, которое определяет PostgreSQL, и всё, что перед ним, что определяете вы. log_line_prefix — это ключ соединения. Каждый факт, позволяющий связать строку с сеансом, транзакцией, клиентом или моментом в журналах другой системы, должен быть в префиксе, потому что само сообщение его не несёт. Значение по умолчанию — '%m [%p] ' начиная с 10; двенадцать лет до этого оно было пустой строкой, и строка журнала PostgreSQL из коробки не имела отметки времени. log_timezone решает, какие часы читает %m.