Оптимизация Postgresql SELECT в Django ORM

Ниже приведен оператор SELECT в PostgreSQL. В настоящее время он возвращает около 300 тыс. строк, что является сгруппированным результатом нескольких миллионов базовых строк. Набор данных будет только увеличиваться. С помощью функции ANALYSE EXPLAIN стоимость этого select составляет 111847 единиц.

Этот оператор select используется в модели набора запросов Django ORM. Таким образом, результаты запрашиваются и отображаются в объект. Из-за времени, затрачиваемого на выполнение SELECT, мое Django-приложение работает с перебоями. Базовые данные состоят из ежедневных временных рядов, но мне не нужна вся история. Я использую набор данных для сгруппированных значений текущего дня, MTD, QTD, YTD, ITD.

Как я могу это оптимизировать? Я изучал индексирование, но не могу найти ему применение. Или я должен просто попытаться перестроить весь запрос? Или даже создать другие таблицы для хранения агрегированных результатов, к которым будет обращаться мой Django ORM?

SELECT customers_data.position_date,
    customers_data.code_id,
    customers_data.book_id,
    customers_data.base_lmv,
    book_tags.book,
    book_tags.market,
    book_tags.employee,
    pnl_data.base_daily_pnl,
    disasters_data.disaster_5_pnl
   FROM ( SELECT daily_customers_holding_scenario.code_id,
            daily_customers_holding_scenario.position_date,
            daily_customers_holding_scenario.book_id,
            sum(daily_customers_holding_scenario.base_lmv) AS base_lmv
           FROM daily_customers_holding_scenario
          GROUP BY daily_customers_holding_scenario.position_date, daily_customers_holding_scenario.code_id, daily_customers_holding_scenario.book_id) customers_data
     LEFT JOIN book_tags ON customers_data.book_id = book_tags.book_id
     FULL JOIN ( SELECT products.position_date,
            products.code_id,
            products.book_id,
            sum(products.palliser_base_pnl) AS base_daily_pnl
           FROM products
          GROUP BY products.position_date, products.code_id, products.book_id) pnl_data ON customers_data.position_date = pnl_data.position_date AND customers_data.code_id::text = pnl_data.code_id::text AND customers_data.book_id = pnl_data.book_id
     LEFT JOIN LATERAL ( SELECT scenarios.code_id,
            scenarios.disaster_book,
            scenarios.disaster_report_date,
            sum(scenarios.disaster_5_pnl) AS disaster_5_pnl
           FROM scenarios
          WHERE scenarios."timestamp" = (( SELECT max(scenarios_1."timestamp") AS max
                   FROM scenarios scenarios_1
                  WHERE scenarios_1.disaster_report_date <= (( SELECT max(daily_pnl_1.position_date) AS max
                           FROM daily_pnl daily_pnl_1))))
          GROUP BY scenarios.code_id, scenarios.disaster_book, scenarios.disaster_report_date) disasters_data ON customers_data.code_id::text = disasters_data.code_id::text AND disasters_data.disaster_book::text = book_tags.book::text;
Вернуться на верх