diff --git a/db/migration/V065__forecast_pv_interval_interval_start_index.sql b/db/migration/V065__forecast_pv_interval_interval_start_index.sql new file mode 100644 index 0000000..24581ab --- /dev/null +++ b/db/migration/V065__forecast_pv_interval_interval_start_index.sql @@ -0,0 +1,8 @@ +-- ============================================================ +-- Forecast PV: urychlení denních/range dotazů podle interval_start +-- (fn_forecast_pv_split, pv-slots* funkce) +-- ============================================================ + +create index if not exists idx_forecast_pv_interval_start_run + on ems.forecast_pv_interval (interval_start, run_id); + diff --git a/db/migration/V066__latest_telemetry_distinct_on_indexes.sql b/db/migration/V066__latest_telemetry_distinct_on_indexes.sql new file mode 100644 index 0000000..e812bdc --- /dev/null +++ b/db/migration/V066__latest_telemetry_distinct_on_indexes.sql @@ -0,0 +1,18 @@ +-- ============================================================= +-- V066__latest_telemetry_distinct_on_indexes.sql +-- Zrychlení view ems.vw_latest_* (PostgREST dashboard endpoints). +-- +-- View používají DISTINCT ON (...) s ORDER BY ... measured_at desc. +-- Bez odpovídajících indexů může plán spadnout na scan+sort nad +-- velkými Timescale hypertabulkami (sekundy latency). +-- ============================================================= + +create index if not exists idx_telemetry_inverter_site_inverter_time_desc + on ems.telemetry_inverter (site_id, inverter_id, measured_at desc); + +create index if not exists idx_telemetry_ev_site_charger_connector_time_desc + on ems.telemetry_ev_charger (site_id, charger_id, connector_id, measured_at desc); + +create index if not exists idx_telemetry_hp_site_heat_pump_time_desc + on ems.telemetry_heat_pump (site_id, heat_pump_id, measured_at desc); + diff --git a/db/routines/R__023_fn_forecast_pv_split.sql b/db/routines/R__023_fn_forecast_pv_split.sql index d85165d..eb7aeef 100644 --- a/db/routines/R__023_fn_forecast_pv_split.sql +++ b/db/routines/R__023_fn_forecast_pv_split.sql @@ -3,10 +3,21 @@ returns jsonb language sql stable as $fn$ - with latest as ( + with tz as ( + select coalesce(nullif(trim(s.timezone), ''), 'Europe/Prague') as tz_name + from ems.site s + where s.id = p_site_id + ), + bounds as ( + select + ((p_day::timestamp) at time zone tz.tz_name) as day_start_utc, + (((p_day + 1)::timestamp) at time zone tz.tz_name) as day_end_utc + from tz + ), + latest as ( select distinct on (fpi.interval_start, fpr.pv_array_id) fpi.run_id, - fpi.pv_array_id, + fpr.pv_array_id, fpi.interval_start, fpi.power_w, fpi.irradiance_wm2, @@ -18,22 +29,15 @@ as $fn$ join ems.asset_pv_array apa on apa.id = fpr.pv_array_id and apa.site_id = fpr.site_id + cross join bounds b where fpr.site_id = p_site_id - and ( - fpi.interval_start at time zone coalesce( - nullif(trim((select timezone from ems.site s where s.id = p_site_id)), ''), - 'Europe/Prague' - ) - )::date = p_day and fpr.status = 'ok' + and fpi.interval_start >= b.day_start_utc + and fpi.interval_start < b.day_end_utc order by fpi.interval_start, fpr.pv_array_id, fpr.created_at desc ), rows as ( select - case - when controllable then 'a' - else 'b' - end as pole, jsonb_build_object( 'run_id', run_id, 'pv_array_id', pv_array_id,