Files
ems/db/routines/R__018_fn_pv_delta_profile_cache.sql
Dusan Vojacek 11767dfdbd
Some checks failed
CI and deploy / deploy (push) Has been cancelled
CI and deploy / migration-check (push) Has been cancelled
HOTFIX výkon: delta-profile cache 44 s/site se přepočítávala každých 15 min
fn_fill_forecast_accuracy (tick :02/:17/:32/:47, 4 lokality) na konci volá
fn_refresh_site_pv_delta_profile_cache → fn_pv_forecast_delta_profile =
agregace 120 dní nad 4.1M řádky forecast_accuracy = ~44 s/site na prod
→ ~3 minuty plné DB zátěže KAŽDOU čtvrthodinu → timeouty /sites a
/health/detailed (30 s), celodenní 'pomalý server'.

Fix: (1) cache refresh throttle 6 h přes delta_profile_cached_at (+p_force;
profil má 14d poločas — 4×/den bohatě stačí); (2) 15min tick lookback
48→3 h (insert část); (3) denní 48h catch-up job 05:50.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:25:27 +02:00

107 lines
2.9 KiB
PL/PgSQL

-- Cache delta profilu PV (těžká agregace forecast_accuracy) — refresh po fn_fill_forecast_accuracy.
-- Prefix R__018: musí běžet před R__022 (volá fn_refresh_site_pv_delta_profile_cache).
drop function if exists ems.fn_refresh_site_pv_delta_profile_cache(int);
create or replace function ems.fn_refresh_site_pv_delta_profile_cache(
p_site_id int,
p_force boolean default false
)
returns void
language plpgsql
as $fn$
declare
v_profile jsonb;
begin
-- VÝKON: agregace 120 dní nad forecast_accuracy trvá ~44 s/site na prod —
-- po 15 min ji přepočítávat dusilo celou DB (timeouty API). Profil má 14d
-- poločas, denní granularitu — čerstvost 6 h bohatě stačí.
if not p_force and exists (
select 1 from ems.site_pv_forecast_calibration c
where c.site_id = p_site_id
and c.delta_profile_cached_at > now() - interval '6 hours'
) then
return;
end if;
v_profile := ems.fn_pv_forecast_delta_profile(
p_site_id,
now() - interval '120 days',
now()
);
update ems.site_pv_forecast_calibration c
set
delta_profile_cache = v_profile,
delta_profile_cached_at = now(),
updated_at = now()
where c.site_id = p_site_id;
if not found then
insert into ems.site_pv_forecast_calibration (
site_id,
delta_learn_min_ts,
delta_profile_cache,
delta_profile_cached_at
)
values (
p_site_id,
timestamptz '2026-04-11T22:00:00Z',
v_profile,
now()
);
end if;
end;
$fn$;
comment on function ems.fn_refresh_site_pv_delta_profile_cache(int) is
'Přepočte a uloží delta_profile_cache pro site (volá fn_pv_forecast_delta_profile).';
create or replace function ems.fn_pv_forecast_delta_profile_cached(
p_site_id int,
p_data_from timestamptz default (now() - interval '120 days'),
p_data_to timestamptz default now(),
p_half_life_days numeric default 14,
p_threshold_w int default 150,
p_top_n_days int default 3,
p_non_top_day_factor numeric default 0.02,
p_day_weight_gamma numeric default 1.0,
p_max_age interval default interval '30 minutes'
)
returns jsonb
language plpgsql
stable
as $fn$
declare
v_cached jsonb;
v_cached_at timestamptz;
begin
select c.delta_profile_cache, c.delta_profile_cached_at
into v_cached, v_cached_at
from ems.site_pv_forecast_calibration c
where c.site_id = p_site_id;
if v_cached is not null
and v_cached_at is not null
and v_cached_at >= now() - p_max_age
and p_data_from >= (now() - interval '120 days')
and p_data_to <= now() + interval '5 minutes' then
return v_cached;
end if;
return ems.fn_pv_forecast_delta_profile(
p_site_id,
p_data_from,
p_data_to,
p_half_life_days,
p_threshold_w,
p_top_n_days,
p_non_top_day_factor,
p_day_weight_gamma
);
end;
$fn$;
comment on function ems.fn_pv_forecast_delta_profile_cached is
'Delta profil z cache (max 30 min) nebo přepočet; pro canonical PV a /plan/current.';