TGViewer
Разработка с Дарьей Матвеевой Разработка с Дарьей Матвеевой @system_design_explained · 72 subscribers
Post #45 339
Появилась задача - оптимизировать сложный аналитический sql-запрос.

Первый возникший вопрос - как измерять эффективность оптимизации. Ведь при повторном выполнении запроса данные кэшируются, и запрос может выполняться на порядки быстрее, чем в первый раз. Существуют хаки для очистки кэшей - остановить Postgresql, очистить кэш ОС. Но это применимо только для локальной БД. В условиях кластера это может не сработать, да и прав на такие действия может не быть.
Остается только ориентироваться на план запроса. Основная цель - на каждом этапе минимизировать количество обрабатываемых строк. В моем случае запрос представлял собой соединение основной таблицы со многими другими, фильтрация по определенным атрибутам, а затем группировка по сущностям из основной таблицы.

План показал, что промежуточные результаты содержали миллионы строк, поэтому группировка была очень медленной. Также, в отчете были необходимы поля из основной таблицы, и для этого по ним тоже проводилась группировка (просто чтобы иметь возможность указать их в select).
Что было сделано:

1. Соединения таблиц с селективными фильтрами были вынесены в подзапрос до группировки, благодаря чему количество группируемых строк уменьшилось до десятков тысяч.

2. Тут оказалось, что количество таблиц, соединяемых в основном подзапросе, оказалось больше 10. В Postgresql после определенного количества соединяемых таблиц (по умолчанию 8) оптимизатор перестает искать оптимальный план и просто обрабатывает их в порядке объявления. А таблица с наиболее селективным фильтром оказалась в конце списка таблиц, поэтому в плане сначала не было заметно никакого улучшения. Но, при перемещении этой таблицы наверх списка, селективный фильтр сработал первым и дал значительное ограничение промежуточных результатов.

3. После группировки еще раз присоединила основную таблицу, чтобы выбрать из нее атрибуты, необходимые в отчете. Так ушла необходимость "протаскивать" их наверх из основного подзапроса, и проводить по ним лишнюю группировку.

Также надо иметь в виду, что оптимизатор Postgresql строит план на основе статистики - количества строк в таблицах, селективности атрибутов, по которым идет фильтрация и т.д.. Поэтому оптимизация, проведенная на dev-стенде, может быть неактуальной для промышленных данных, и ее надо обязательно протестировать на prod-стенде.

#рабочее
  • 🔥 3
More from @system_design_explained
  1. Sep 22, 2026Нашла способ, который мгновенно и без дополнительных усилий увеличил мою продуктивность пр…
  2. Mar 27, 2026Я в ВК : https://vk.ru/dev_with_dm
  3. Mar 27, 2026Читаю в последнее время много критики микросервисов, и у меня тоже есть пример, как раз за…
  4. Mar 4, 2026В функциональных языках рекомендуется делать все объекты immutable, и, хотя на работе я пи…
  5. Dec 4, 2025Недавно занималась задачей, где нужно было реализовать оптимистическую блокировку сущности…
  6. Nov 21, 2025Обнаружила еще один плюс TDD. Согласно подходу, я пишу тест, который падает, пишу код, что…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →