Оптимизация 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;