Оптимизация оператора Select в PostgresSQL
Ниже приведен оператор SELECT в PostgreSQL. В настоящее время он возвращает около 300 тыс. строк, что является сгруппированным результатом нескольких миллионов базовых строк. Набор данных будет только увеличиваться. С помощью функции ANALYSE EXPLAIN стоимость этого select составляет 111847 единиц.
Этот оператор select используется в модели набора запросов Django ORM. Таким образом, результаты запрашиваются и отображаются в объект. Из-за времени, затрачиваемого на выполнение SELECT, мое Django-приложение работает с перебоями. Базовые данные состоят из ежедневных временных рядов, но мне не нужна вся история. Я использую набор данных для сгруппированных значений текущего дня, MTD, QTD, YTD, ITD.
Как я могу это оптимизировать? Я изучал индексирование, но не могу применить его здесь, и поэтому не использую никаких индексов.
SELECT exposures_data.position_date,
exposures_data.enfusion_id,
exposures_data.book_id,
exposures_data.base_lmv,
book_tags.book,
book_tags.portfolio,
book_tags.analyst,
pnl_data.base_daily_pnl,
disasters_data.disaster_5_pnl
FROM ( SELECT daily_exposures_holding_scenario.enfusion_id,
daily_exposures_holding_scenario.position_date,
daily_exposures_holding_scenario.book_id,
sum(daily_exposures_holding_scenario.base_lmv) AS base_lmv
FROM daily_exposures_holding_scenario
GROUP BY daily_exposures_holding_scenario.position_date, daily_exposures_holding_scenario.enfusion_id, daily_exposures_holding_scenario.book_id) exposures_data
LEFT JOIN book_tags ON exposures_data.book_id = book_tags.book_id
FULL JOIN ( SELECT gl_daily_pnl.position_date,
gl_daily_pnl.enfusion_id,
gl_daily_pnl.book_id,
sum(gl_daily_pnl.palliser_base_pnl) AS base_daily_pnl
FROM gl_daily_pnl
GROUP BY gl_daily_pnl.position_date, gl_daily_pnl.enfusion_id, gl_daily_pnl.book_id) pnl_data ON exposures_data.position_date = pnl_data.position_date AND exposures_data.enfusion_id::text = pnl_data.enfusion_id::text AND exposures_data.book_id = pnl_data.book_id
LEFT JOIN LATERAL ( SELECT disaster_scenarios.enfusion_id,
disaster_scenarios.disaster_book,
disaster_scenarios.disaster_report_date,
sum(disaster_scenarios.disaster_5_pnl) AS disaster_5_pnl
FROM disaster_scenarios
WHERE disaster_scenarios."timestamp" = (( SELECT max(disaster_scenarios_1."timestamp") AS max
FROM disaster_scenarios disaster_scenarios_1
WHERE disaster_scenarios_1.disaster_report_date <= (( SELECT max(daily_pnl_1.position_date) AS max
FROM daily_pnl daily_pnl_1))))
GROUP BY disaster_scenarios.enfusion_id, disaster_scenarios.disaster_book, disaster_scenarios.disaster_report_date) disasters_data ON exposures_data.enfusion_id::text = disasters_data.enfusion_id::text AND disasters_data.disaster_book::text = book_tags.book::text;
Пожалуйста, посмотрите следующий вывод EXPLAIN:
А DDL таблиц: