TuBrief
구독 채널
비디오
커뮤니티

Как ускорить рекурсивные запросы с помощью новых функций Postgres

TuBrief 편집팀
2026년 8월 7일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

Русский한국어EnglishEspañol中文العربيةहिन्दीDeutschPortuguêsBahasa IndonesiaFrançais日本語

관련 영상

Postgres выпускает потрясающую новую функцию7:45

Postgres выпускает потрясающую новую функцию

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Как ускорить рекурсивные запросы с помощью новых функций Postgres

В тот момент, когда рекурсивный запрос останавливается

Рекурсивные CTE, используемые для обхода отношений между родителями и потомками или множественных путей в устаревших системах, ломаются по мере увеличения глубины данных. В тот момент, когда веер индекса (index fan-out) начинает сбоить, движок создает временную таблицу на каждом шаге и выполняет повторные самосоединения (self-joins). Результирующий набор заполняет память и переливается на диск, вызывая spillover. Ввод-вывод блокируется, а ЦП истощается. Встроенный синтаксис CYCLE, появившийся в PostgreSQL 14, снижает затраты на поиск по массиву, но по мере увеличения глубины обхода затраты на повторные поиски по вторичным индексам и копирование памяти больших кортежей остаются прежними.

Чтобы увеличить скорость запросов и сэкономить ЦП, следует перейти на встроенный синтаксис графов на базе SQL/PGQ. Во-первых, используйте синтаксис CREATE PROPERTY GRAPH, оставляя физическую структуру существующих реляционных таблиц без изменений. Укажите таблицы отдельных сущностей как VERTEX TABLES, а таблицы пересечений «многие ко многим» — как EDGE TABLES. во-вторых, поскольку колонки, указанные в качестве ключей, не попадают в свойства графа автоматически, добавьте поля в предложение PROPERTIES, чтобы обеспечить права фильтрации GRAPH_TABLE. В-третьих, для запросов, у которых глубина обхода превышает 3 уровня, средний коэффициент ветвления составляет 10 или более, а количество кортежей превышает 10 миллионов, замените их на паттерн GRAPH_TABLE MATCH. Сложный рекурсивный код сократится до одной строки паттерна, а использование буфера памяти заметно уменьшится.

Атомарная обработка данных для предотвращения конфликтов параллелизма

Ошибки дублирования вставки, возникающие, когда несколько потоков одновременно передают данные в распределенной среде, невозможно устранить с помощью блокировок приложения. Возникают накладные расходы на сетевой RTT, и гонка данных (race condition) срабатывает в зазоре непосредственно перед фиксацией транзакции. Необходимо инкорпорировать блокировки на уровне строк с помощью конструкций INSERT ON CONFLICT и MERGE. Конструкция ON CONFLICT использует спекулятивную технику вставки для блокировки страницы уникального индекса и попытки вставки. Если происходит конфликт, она немедленно разветвляется в DO UPDATE или DO NOTHING, снижая частоту сеансов дедлоков.

Изменение уровня изоляции транзакций при использовании атомарных конструкций оказывает большой побочный эффект. В READ COMMITTED последующая транзакция ожидает фиксации предыдущей транзакции, а затем повторно считывает последние кортежи для безопасной обработки. Однако при повышении до REPEATABLE READ или SERIALIZABLE при возникновении конфликта с предыдущей транзакцией она без ожидания выдает ошибку сбоя сериализации и выполняет откат. Чтобы сократить затраты на откат и предотвратить исчерпание пула соединений, цикл повторных попыток следует применять только к кодам ошибок 40001 и 40P01. Добавьте случайное значение джиттера к базовому времени ожидания, чтобы разбросать моменты попыток, и ограничьте максимальное количество повторных попыток от 3 до 5 раз, прежде чем передать ошибку на верхний бизнес-уровень.

Очистка хранилища больших таблиц без простоя сервиса

Определение момента, когда фрагментация блоков и накопившиеся мертвые кортежи снижают эффективность сканирования индекса, является отправной точкой управления хранилищем. Из-за особенностей архитектуры MVCC мертвые кортежи, созданные с помощью UPDATE или DELETE, не возвращаются ОС сразу, а остаются в виде фрагментации. При совместном рассмотрении метрики n_dead_tup в представлении pg_stat_user_tables и расширения pgstattuple, если коэффициент dead_tuple_ratio превышает 20 процентов или доля free_space составляет 30 процентов, необходимо освободить дисковое пространство. Если оставить это без внимания, чтение блоков ввода-вывода увеличится, а эффективность буферного пула будет нарушена.

Чтобы освободить хранилище в фоновом режиме без остановки сервиса, используйте утилиту pg_repack. Во-первых, создайте теневую таблицу (shadow table) целевой исходной таблицы и добавьте триггер логирования для отслеживания изменений. Во-вторых, массово скопируйте действительные кортежи в теневую таблицу, асинхронно и параллельно пересоздайте индексы, а затем замените системный каталог. В-третьих, выполните команду фонового процесса напрямую из терминала.

`bash
pg_repack
--dbname=production_db
--table=public.orders
--jobs=4
--wait-timeout=10
--no-superuser-check

`

Чтобы предотвратить состязание за блокировки (lock contention), установите SET lock_timeout = '3s'; на уровне сеанса, чтобы в случае невозможности захвата блокировки в течение 3 секунд запрос не задерживался в очереди, а сразу выдавал ошибку. Добавьте опцию --wait-timeout=10, чтобы прервать ситуацию, когда последующие запросы блокируются каскадом.

Фиксация планов запросов, нарушенных несоответствием статистической информации

Если цикл сбора статистики нарушен и план запроса внезапно меняется, это приводит к сбою в рабочей среде. В местах скопления тяжелых операций статистика и фактическое распределение данных расходятся, что приводит к переключению планов (plan flip). Если оптимизатор выбирает соединение Nested Loop вместо сканирования индекса, происходят скачки ЦП и возникают узкие места ввода-вывода. Диагностика возможна только в том случае, если добавить модуль auto_explain в shared_preload_libraries и установить log_min_duration равным 500 миллисекундам для записи фактического плана выполнения медленных запросов в системный журнал сервера.

Чтобы принудительно зафиксировать путь выполнения определенного запроса, используются модули подсказок (hints). После обнаружения проблемного запроса в логах установите расширение pg_hint_plan и добавьте комментарий перед инструкцией SQL или зарегистрируйте запрос в таблице каталога hint_plan.hints. Если исходный код сложно развернуть, можно напрямую внедрить строку статического хинта на уровне каталога, чтобы немедленно зафиксировать план без повторного развертывания. Это самый быстрый способ защитить скорость ответа на запросы в экстренных ситуациях, когда повторный сбор статистики или пересоздание индекса занимают много времени.