Perf ROOT CAUSE: rolling faktor se počítal per řádek — hoist do proměnné (canonical PV fn 4.5s→~0.45s)
Skutečná příčina 600k buffers: CTE factor/factor_raw (single-ref) PG inlinuje do projekce with_factor → fn_pv_forecast_correction_factor (48 ms / 1.9k buffers) se vyhodnocovala ~300× per výstupní slot. Plan cache s tím neměl nic společného (dřívější count(*) měření projekci zahodilo, proto vycházelo 0.42 s). Faktor se teď počítá jednou do v_rolling_factor a vkládá jako literál (13. argument format). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,21 @@ set work_mem = '64MB'
|
||||
as $fn$
|
||||
declare
|
||||
v_result jsonb;
|
||||
v_rolling_factor numeric;
|
||||
begin
|
||||
-- Rolling faktor JEDNOU do proměnné: jako inlinovaná CTE (single-ref) se
|
||||
-- fn_pv_forecast_correction_factor vyhodnocovala per výstupní řádek
|
||||
-- (~300× ≈ 570k buffers / ~4 s — skutečná příčina pomalosti, ne plan cache).
|
||||
v_rolling_factor := coalesce(
|
||||
(ems.fn_pv_forecast_correction_factor(
|
||||
p_site_id,
|
||||
(p_now - (p_factor_window_h::text || ' hours')::interval)::timestamptz,
|
||||
p_now,
|
||||
p_factor_min_clamp,
|
||||
p_factor_max_clamp
|
||||
)->>'correction_factor')::numeric,
|
||||
1.0
|
||||
);
|
||||
-- PG 18 cachuje plán SQL/plpgsql statementů s parametry → generický plán
|
||||
-- (4.5–9 s / 600k buffers); force_custom_plan na funkci nepomohl. Execute
|
||||
-- s literály vynutí čerstvý plán dle skutečných hodnot: 0.4 s / 34k buffers.
|
||||
@@ -70,20 +84,6 @@ begin
|
||||
from slot_spine s
|
||||
cross join tz t
|
||||
),
|
||||
factor_raw as (
|
||||
select ems.fn_pv_forecast_correction_factor(
|
||||
%1$s,
|
||||
(%4$L::timestamptz - (%9$s::text || ' hours')::interval)::timestamptz,
|
||||
%4$L::timestamptz,
|
||||
%10$s,
|
||||
%11$s
|
||||
) as j
|
||||
),
|
||||
factor as (
|
||||
select
|
||||
coalesce((j->>'correction_factor')::numeric, 1.0::numeric) as rolling_factor
|
||||
from factor_raw
|
||||
),
|
||||
profile as (
|
||||
select ems.fn_pv_forecast_delta_profile_cached(
|
||||
%1$s,
|
||||
@@ -194,18 +194,17 @@ begin
|
||||
ab.pv_b_forecast_raw_w,
|
||||
ab.pv_a_forecast_delta_w,
|
||||
ab.pv_b_forecast_delta_w,
|
||||
f.rolling_factor,
|
||||
%13$s::numeric as rolling_factor,
|
||||
case
|
||||
when ab.interval_start < b.now_slot then 1.0::numeric
|
||||
when %12$s <= 0 then f.rolling_factor
|
||||
when %12$s <= 0 then %13$s::numeric
|
||||
else
|
||||
case
|
||||
when ((extract(epoch from (ab.interval_start - b.now_slot)) / 900)::int) >= %12$s then 1.0::numeric
|
||||
else (1.0::numeric + (f.rolling_factor - 1.0::numeric) * (1.0::numeric - ((extract(epoch from (ab.interval_start - b.now_slot)) / 900)::numeric / %12$s::numeric)))
|
||||
else (1.0::numeric + (%13$s::numeric - 1.0::numeric) * (1.0::numeric - ((extract(epoch from (ab.interval_start - b.now_slot)) / 900)::numeric / %12$s::numeric)))
|
||||
end
|
||||
end as rolling_effective_factor
|
||||
from fc_ab ab
|
||||
cross join factor f
|
||||
cross join bounds b
|
||||
)
|
||||
select coalesce(
|
||||
@@ -242,7 +241,8 @@ $q$,
|
||||
p_factor_window_h,
|
||||
p_factor_min_clamp,
|
||||
p_factor_max_clamp,
|
||||
p_decay_slots
|
||||
p_decay_slots,
|
||||
v_rolling_factor
|
||||
) into v_result;
|
||||
return coalesce(v_result, '[]'::jsonb);
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user