Оптимизация оператора 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 таблиц:

Вернуться на верх