REPLACE VIEW agency.task_fact AS (
SELECT
*,
atomic_gross_profit / atomic_expense AS atomic_roi
FROM (
SELECT
*,
atomic_income - atomic_expense AS atomic_gross_profit
FROM (
SELECT
id,
atomic_hour_rate_rub,
atomic_hour_price_rub,
atomic_duration_hours,
atomic_duration_hours * atomic_hour_rate_rub AS atomic_expense,
atomic_duration_hours * atomic_hour_price_rub AS atomic_income,
Полностью:
https://gist.github.com/GreenRobot777/e37457f5a72f033cb9575b272aa456e2
По-моему, использование ORDER BY в view — это грубая ошибка, потому что это на самом деле не гарантирует ничего, кроме тормозов. А в остальном — как обычно: https://t.me/pgsql/288632
Скорость пофиксил тем, что перешёл на MATERIALIZED VIEW.
Тут вычисления используют результаты предыдущих вычислений, для этого используются вложенные SELECTы. Есть ли разница между тем, чтобы делать вложенные селекты и явно показывать, что посчитанные значения можно переиспользовать или можно писать всё в одном селекте (делать одни и те же умножения несколько раз) и оптимизатор сам поймёт, что их можно переиспользовать? Где можно про это прочитать в доке?
а нельзя там эти данные генерировать на триггерах сразу в нужной форме?
А почему Вы ничего другого показывать / пробовать не стали? И Вы понимаете, что запрос и mat.view — совсем не одно и то же?
Я бы переписал на один select с кучей left join'ов
Типа вот такого, только тут порядок столбцов обратный, уж извините CREATE OR REPLACE VIEW agency.task_fact AS ( select t.id, t.name, min(tie.started_at) as started_at, max(tie.ended_at) as ended_at, sum(tie.duration_hours) as atomic_duration_hours, sum(tie.duration_hours) * con.hour_rate_rub AS atomic_expense, sum(tie.duration_hours) * sum(d.hour_price_rub) AS atomic_income, con.hour_rate_rub as atomic_hour_rate_rub, sum(d.hour_price_rub) as atomic_hour_price_rub, t.user_story__id, fe.id as feature__id, ep.id as epic__id, prj.id as project__id, prg.id as program__id, t.contract__id, t.payout__id, cr.id as contractor__id, te.id as team__id, tel.id as team_lead__id, crl.id as contractor_level__id, t.release__id, pr.id as product__id, prc.id as product_class__id, ((sum(tie.duration_hours) * sum(d.hour_price_rub)) - (sum(tie.duration_hours) * con.hour_rate_rub)) / (sum(tie.duration_hours) * con.hour_rate_rub) as atomic_roi, (sum(tie.duration_hours) * sum(d.hour_price_rub)) - (sum(tie.duration_hours) * con.hour_rate_rub) as atomic_gross_profit from agency.task t left join agency.release r on r.id = t.release__id left join agency.product pr on pr.id = r.product__id left join agency.product_class prc on prc.id = pr.product_class__id left join agency.contract con on con.id = t.contract__id left join agency.contractor cr on cr.id = con.contractor__id left join agency.contractor_level crl on crl.id = cr.contractor_level__id left join agency.team te on te.id = con.team__id left join agency.team_lead tel on tel.id = te.team_lead__id left join agency.user_story us on us.id = t.user_story__id left join agency.feature fe on fe.id = us.feature__id left join agency.epic ep on ep.id = fe.epic__id left join agency.project pr on prj on prj.id = ep.project__id left join agency.program prg on prg.id = prg.program__id left join agency.task__deal td on td.task__id = t.id left join agency.deal d on d.id = td.deal__id left join agency.time_entry tie on tie.task__id = t.id group by t.id, t.name, con.hour_rate_rub, t.user_story__id, fe.id, ep.id, prj.id, prg.id, t.contract__id, t.payout__id, cr.id, te.id, tel.id, crl.id, t.release__id, pr.id, prc.id );
А что Вы имеете в виду, конкретно? Что-то вроде SELECT (a+b)*(a-b) FROM (SELECT c*d AS a, e*f AS b FROM ...) AS t1 против SELECT (c*d+e*f)*(c*d-e*f) FROM ...?
А по вычислениям это будет реально дешевле? Или только для удобства восприятия?
Дешевле чем что? Мне кажется, или Вы до сих пор не задали конкретного вопроса, а на уточняющие не ответили? ;) Или я пропустил?
В принципе, без знания таблиц и их содержимого сложно так навскидку сказать, но то, что у вас в текущей реализации вьюхи к одной и той же таблице по 4-5 раз обращения в подзапросах происходят, как мне кажется, с переходом на left join'ы быстродействие должно увеличиться
Да, есть ли разница по стоимости вычисления или оптимизатор в данном случае увидит дублирующиеся вычисления и выполнит умножение один раз? Буду благодарен, если ткнёте в раздел документации, где об этом пишут или подскажете, куда копать.
Нет, планировщик не ищет дубли вычислений (не считая GROUP BY, где это необходимо по смыслу). Не помню, чтобы об этом было написано в документации — это несущественная деталь реализации.
Обсуждают сегодня