Given this view
CREATE OR REPLACE VIEW public."SellMeta"
AS WITH wh AS (
SELECT "WWHH".id,
"WWHH".url,
"WWHH".name,
"WWHH".ttt
FROM "WWHH"
), fj AS (
SELECT "FFF".id,
"FFF".aaa,
"FFF".mmm,
"FFF".bbb,
"FFF"."ccc",
"FFF"."iId"
FROM "FFF"
)
SELECT i.id,
i."pId",
i.rrr,
i."ccc",
i.eee,
i.ttt,
fjj."wwwList",
to_jsonb(wh.*) AS wh2,
i.vat
FROM "Sell" i
LEFT JOIN LATERAL ( SELECT jsonb_agg(to_jsonb(fj.*) #- '{iId}'::text[] ORDER BY fj.aaa DESC, fj.mmm DESC, fj.bbb DESC) AS "wwwList",
1 AS k
FROM fj
WHERE fj."iId" = i.id
GROUP BY 1::integer) fjj ON true
LEFT JOIN wh ON i."whId" = wh.id;
This query is very slow:
select
"SellMeta" .* as "i",
case
when l.id is null then null
else jsonb_bbb_object('id', l."id", 'code', l."code", 'kind', l."kind")
end as "licence"
from
"SellMeta"
left join "Licence" as "l" on
"l"."id" = "SellMeta"."pId"
order by
"ccc" desc,
"id" desc
limit 25
This is the relative plan
Limit (cost=28088832.32..28088832.38 rows=25 width=669) (actual time=8391.716..8391.720 rows=25 loops=1)
-> Sort (cost=28088832.32..28089220.98 rows=155463 width=669) (actual time=8232.079..8232.082 rows=25 loops=1)
Sort Key: i."ccc" DESC, i.id DESC
Sort Method: top-N heapsort Memory: 49kB
-> Nested Loop Left Join (cost=5.06..28084445.27 rows=155463 width=669) (actual time=0.117..8171.565 rows=155463 loops=1)
-> Nested Loop Left Join (cost=4.78..28034018.83 rows=155463 width=637) (actual time=0.100..7698.774 rows=155463 loops=1)
Join Filter: (i."whId" = "WWHH".id)
-> Nested Loop Left Join (cost=4.78..27894379.09 rows=155463 width=621) (actual time=0.095..7667.807 rows=155463 loops=1)
-> Seq Scan on "Sell" i (cost=0.00..3321.63 rows=155463 width=589) (actual time=0.018..21.796 rows=155463 loops=1)
-> GroupAggregate (cost=4.78..179.39 rows=1 width=36) (actual time=0.049..0.049 rows=1 loops=155463)
Group Key: 1
-> Bitmap Heap Scan on "FFF" (cost=4.78..178.92 rows=45 width=56) (actual time=0.004..0.009 rows=11 loops=155463)
Recheck Cond: ("iId" = i.id)
Heap Blocks: exact=1746805
-> Bitmap Index Scan on aaajournal_instanceid_idx (cost=0.00..4.77 rows=45 width=0) (actual time=0.002..0.002 rows=11 loops=155463)
Index Cond: ("iId" = i.id)
-> Materialize (cost=0.00..10.90 rows=60 width=48) (actual time=0.000..0.000 rows=0 loops=155463)
-> Seq Scan on "WWHH" (cost=0.00..10.60 rows=60 width=48) (actual time=0.002..0.002 rows=0 loops=1)
-> Index Scan using "Licence_pkey" on "Licence" l (cost=0.29..0.31 rows=1 width=50) (actual time=0.001..0.001 rows=1 loops=155463)
Index Cond: (id = i."pId")
Planning Time: 0.860 ms
JIT:
Functions: 23
Options: Inlining true, Optimization true, Expressions true, Deforming true
Timing: Generation 2.218 ms, Inlining 20.417 ms, Optimization 80.113 ms, Emission 59.120 ms, Total 161.867 ms
Execution Time: 8394.096 ms
But if i refactor replacing the VIEW using WITH
with wh as (
select
"WWHH".id,
"WWHH".url,
"WWHH".name,
"WWHH".ttt
from
"WWHH"
),
fj as (
select
"FFF".id,
"FFF".aaa,
"FFF".mmm,
"FFF".bbb,
"FFF"."ccc",
"FFF"."iId"
from
"FFF"
),
"SellMeta" as (
select
i.id,
i."pId",
i.rrr,
i."ccc",
i.eee,
i.ttt,
fjj."wwwList",
to_jsonb(wh.*) as wh2,
i.vat
from
"Sell" i
left join lateral (
select
jsonb_agg(to_jsonb(fj.*) #- '{iId}'::text[] order by fj.aaa desc, fj.mmm desc, fj.bbb desc) as "wwwList",
1 as k
from
fj
where
fj."iId" = i.id
group by
1::integer) fjj on
true
left join wh on
i."whId" = wh.id)
select
"SellMeta" .* as "i",
case
when l.id is null then null
else jsonb_bbb_object('id', l."id", 'code', l."code", 'kind', l."kind")
end as "licence"
from
"SellMeta"
left join "Licence" as "l" on
"l"."id" = "SellMeta"."pId"
order by
"ccc" desc,
"id" desc
limit 25
The query is much faster
This is the plan
Limit (cost=5.48..4522.91 rows=25 width=669) (actual time=0.287..1.161 rows=25 loops=1)
-> Nested Loop Left Join (cost=5.48..28091742.90 rows=155463 width=669) (actual time=0.285..1.154 rows=25 loops=1)
-> Nested Loop Left Join (cost=5.20..28042482.43 rows=155463 width=637) (actual time=0.229..0.798 rows=25 loops=1)
Join Filter: (i."whId" = "WWHH".id)
-> Nested Loop Left Join (cost=5.20..27903231.35 rows=155463 width=621) (actual time=0.219..0.774 rows=25 loops=1)
-> Index Scan using created_sort_idx on "Sell" i (cost=0.42..12173.89 rows=155463 width=589) (actual time=0.080..0.106 rows=25 loops=1)
-> GroupAggregate (cost=4.78..179.39 rows=1 width=36) (actual time=0.025..0.025 rows=1 loops=25)
Group Key: 1
-> Bitmap Heap Scan on "FFF" (cost=4.78..178.92 rows=45 width=56) (actual time=0.010..0.010 rows=1 loops=25)
Recheck Cond: ("iId" = i.id)
Heap Blocks: exact=21
-> Bitmap Index Scan on aaajournal_instanceid_idx (cost=0.00..4.77 rows=45 width=0) (actual time=0.008..0.008 rows=1 loops=25)
Index Cond: ("iId" = i.id)
-> Materialize (cost=0.00..10.90 rows=60 width=48) (actual time=0.000..0.000 rows=0 loops=25)
-> Seq Scan on "WWHH" (cost=0.00..10.60 rows=60 width=48) (actual time=0.005..0.005 rows=0 loops=1)
-> Index Scan using "Licence_pkey" on "Licence" l (cost=0.29..0.31 rows=1 width=50) (actual time=0.009..0.009 rows=1 loops=25)
Index Cond: (id = i."pId")
Planning Time: 1.549 ms
Execution Time: 1.280 ms
Why using the View instead of an inline WITH has a so great performance impact?
I'm using Postgresql 15.1
order by "ccc" desc,"id" desc
to the view then the performance improve like the 'WITH' version. Not sure why this happen.