Výkon: vw_latest_inverter / vw_latest_ev_charger přepis na LATERAL
DISTINCT ON třídilo ~195k/277k řádků hypertable při každém čtení (fn_site_full_status 1.7 s). LATERAL limit 1 per zařízení jde po PK indexu. Ověřeno na živé DB: identické výsledky, inverter 508→56 ms, EV 460→75 ms. EV konektory: discovery za 30 dní (tabulka konektorů neexistuje; mrtvý konektor po 30 dnech z latest pohledu zmizí — vědomá změna sémantiky). Sloupce i pořadí beze změny (create or replace view kompatibilní). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,90 +2,140 @@
|
|||||||
-- R__058_vw_latest_telemetry.sql
|
-- R__058_vw_latest_telemetry.sql
|
||||||
-- EMS Platform – aktuální stav všech zařízení per lokalita
|
-- EMS Platform – aktuální stav všech zařízení per lokalita
|
||||||
-- Repeatable migration
|
-- Repeatable migration
|
||||||
|
--
|
||||||
|
-- Výkon (audit 2026-06-11): původní DISTINCT ON přes celé hypertable
|
||||||
|
-- třídilo ~195k (inverter) / ~277k (EV) řádků při každém čtení
|
||||||
|
-- (fn_site_full_status ~1.7 s). LATERAL limit 1 per zařízení čte jen
|
||||||
|
-- špičku PK indexu ((inverter_id|charger_id, …, measured_at)).
|
||||||
-- =============================================================
|
-- =============================================================
|
||||||
|
|
||||||
-- security_invoker = false: oprávnění na podkladové hypertably nemusí mít ems_anon (PostgREST).
|
-- security_invoker = false: oprávnění na podkladové hypertably nemusí mít ems_anon (PostgREST).
|
||||||
CREATE OR REPLACE VIEW ems.vw_latest_inverter
|
create or replace view ems.vw_latest_inverter
|
||||||
WITH (security_invoker = false)
|
with (security_invoker = false)
|
||||||
AS
|
as
|
||||||
SELECT DISTINCT ON (t.inverter_id)
|
select
|
||||||
t.site_id,
|
inv.site_id,
|
||||||
t.inverter_id,
|
inv.id as inverter_id,
|
||||||
inv.code AS inverter_code,
|
inv.code as inverter_code,
|
||||||
t.measured_at,
|
t.measured_at,
|
||||||
t.pv_power_w,
|
t.pv_power_w,
|
||||||
t.battery_soc_percent,
|
t.battery_soc_percent,
|
||||||
t.battery_power_w,
|
t.battery_power_w,
|
||||||
t.grid_power_w,
|
t.grid_power_w,
|
||||||
t.load_power_w,
|
t.load_power_w,
|
||||||
t.inverter_temp_c,
|
t.inverter_temp_c,
|
||||||
t.operating_mode,
|
t.operating_mode,
|
||||||
t.fault_code,
|
t.fault_code,
|
||||||
now() - t.measured_at AS data_age,
|
now() - t.measured_at as data_age,
|
||||||
t.pv1_power_w,
|
t.pv1_power_w,
|
||||||
t.pv2_power_w,
|
t.pv2_power_w,
|
||||||
t.gen_port_power_w,
|
t.gen_port_power_w,
|
||||||
t.batt_charge_today_wh,
|
t.batt_charge_today_wh,
|
||||||
t.batt_discharge_today_wh,
|
t.batt_discharge_today_wh,
|
||||||
t.run_state,
|
t.run_state,
|
||||||
t.is_export_limited,
|
t.is_export_limited,
|
||||||
t.pv_derating_flags
|
t.pv_derating_flags
|
||||||
FROM ems.telemetry_inverter t
|
from ems.asset_inverter inv
|
||||||
JOIN ems.asset_inverter inv ON inv.id = t.inverter_id
|
left join lateral (
|
||||||
ORDER BY t.inverter_id, t.measured_at DESC;
|
select
|
||||||
|
ti.measured_at,
|
||||||
|
ti.pv_power_w,
|
||||||
|
ti.battery_soc_percent,
|
||||||
|
ti.battery_power_w,
|
||||||
|
ti.grid_power_w,
|
||||||
|
ti.load_power_w,
|
||||||
|
ti.inverter_temp_c,
|
||||||
|
ti.operating_mode,
|
||||||
|
ti.fault_code,
|
||||||
|
ti.pv1_power_w,
|
||||||
|
ti.pv2_power_w,
|
||||||
|
ti.gen_port_power_w,
|
||||||
|
ti.batt_charge_today_wh,
|
||||||
|
ti.batt_discharge_today_wh,
|
||||||
|
ti.run_state,
|
||||||
|
ti.is_export_limited,
|
||||||
|
ti.pv_derating_flags
|
||||||
|
from ems.telemetry_inverter ti
|
||||||
|
where ti.inverter_id = inv.id
|
||||||
|
order by ti.measured_at desc
|
||||||
|
limit 1
|
||||||
|
) t on true
|
||||||
|
where t.measured_at is not null;
|
||||||
|
|
||||||
COMMENT ON VIEW ems.vw_latest_inverter IS
|
comment on view ems.vw_latest_inverter is
|
||||||
'Nejnovější telemetrická data pro každý střídač. Slouží pro real-time dashboard a health check.';
|
'Nejnovější telemetrická data pro každý střídač (LATERAL per-inverter, PK index). Slouží pro real-time dashboard a health check.';
|
||||||
|
|
||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
CREATE OR REPLACE VIEW ems.vw_latest_ev_charger
|
create or replace view ems.vw_latest_ev_charger
|
||||||
WITH (security_invoker = false)
|
with (security_invoker = false)
|
||||||
AS
|
as
|
||||||
SELECT DISTINCT ON (t.charger_id, t.connector_id)
|
select
|
||||||
t.site_id,
|
ch.site_id,
|
||||||
t.charger_id,
|
ch.id as charger_id,
|
||||||
ch.code AS charger_code,
|
ch.code as charger_code,
|
||||||
t.connector_id,
|
conn.connector_id,
|
||||||
t.measured_at,
|
t.measured_at,
|
||||||
t.status,
|
t.status,
|
||||||
t.power_w,
|
t.power_w,
|
||||||
t.energy_kwh,
|
t.energy_kwh,
|
||||||
t.current_a,
|
t.current_a,
|
||||||
t.session_id,
|
t.session_id,
|
||||||
t.error_code,
|
t.error_code,
|
||||||
now() - t.measured_at AS data_age
|
now() - t.measured_at as data_age
|
||||||
FROM ems.telemetry_ev_charger t
|
from ems.asset_ev_charger ch
|
||||||
JOIN ems.asset_ev_charger ch ON ch.id = t.charger_id
|
-- konektory za posledních 30 dní (tabulka konektorů neexistuje; konektor bez
|
||||||
ORDER BY t.charger_id, t.connector_id, t.measured_at DESC;
|
-- telemetrie 30 dní je pro „latest“ dashboard mrtvý)
|
||||||
|
left join lateral (
|
||||||
|
select distinct tc.connector_id
|
||||||
|
from ems.telemetry_ev_charger tc
|
||||||
|
where tc.charger_id = ch.id
|
||||||
|
and tc.measured_at >= now() - interval '30 days'
|
||||||
|
) conn on true
|
||||||
|
left join lateral (
|
||||||
|
select
|
||||||
|
te.measured_at,
|
||||||
|
te.status,
|
||||||
|
te.power_w,
|
||||||
|
te.energy_kwh,
|
||||||
|
te.current_a,
|
||||||
|
te.session_id,
|
||||||
|
te.error_code
|
||||||
|
from ems.telemetry_ev_charger te
|
||||||
|
where te.charger_id = ch.id
|
||||||
|
and te.connector_id = conn.connector_id
|
||||||
|
order by te.measured_at desc
|
||||||
|
limit 1
|
||||||
|
) t on true
|
||||||
|
where t.measured_at is not null;
|
||||||
|
|
||||||
COMMENT ON VIEW ems.vw_latest_ev_charger IS
|
comment on view ems.vw_latest_ev_charger is
|
||||||
'Nejnovější telemetrická data pro každý konektor EV nabíječky. Slouží pro dashboard a řízení nabíjení.';
|
'Nejnovější telemetrická data pro každý konektor EV nabíječky (LATERAL per-konektor, PK index). Slouží pro dashboard a řízení nabíjení.';
|
||||||
|
|
||||||
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
CREATE OR REPLACE VIEW ems.vw_latest_heat_pump
|
create or replace view ems.vw_latest_heat_pump
|
||||||
WITH (security_invoker = false)
|
with (security_invoker = false)
|
||||||
AS
|
as
|
||||||
SELECT
|
select
|
||||||
hp.site_id,
|
hp.site_id,
|
||||||
hp.id AS heat_pump_id,
|
hp.id as heat_pump_id,
|
||||||
hp.code AS heat_pump_code,
|
hp.code as heat_pump_code,
|
||||||
t.measured_at,
|
t.measured_at,
|
||||||
t.outdoor_temp_c,
|
t.outdoor_temp_c,
|
||||||
t.tuv_tank_temp_c,
|
t.tuv_tank_temp_c,
|
||||||
t.water_outlet_temp_c,
|
t.water_outlet_temp_c,
|
||||||
t.power_w,
|
t.power_w,
|
||||||
t.operating_mode,
|
t.operating_mode,
|
||||||
t.cop_actual,
|
t.cop_actual,
|
||||||
t.defrost_active,
|
t.defrost_active,
|
||||||
t.alarm_code,
|
t.alarm_code,
|
||||||
-- Odhadovaný COP pro aktuální venkovní teplotu
|
-- Odhadovaný COP pro aktuální venkovní teplotu
|
||||||
ems.fn_cop_estimate(hp.id, t.outdoor_temp_c) AS cop_estimated,
|
ems.fn_cop_estimate(hp.id, t.outdoor_temp_c) as cop_estimated,
|
||||||
now() - t.measured_at AS data_age
|
now() - t.measured_at as data_age
|
||||||
FROM ems.asset_heat_pump hp
|
from ems.asset_heat_pump hp
|
||||||
LEFT JOIN LATERAL (
|
left join lateral (
|
||||||
SELECT
|
select
|
||||||
thp.measured_at,
|
thp.measured_at,
|
||||||
thp.outdoor_temp_c,
|
thp.outdoor_temp_c,
|
||||||
thp.tuv_tank_temp_c,
|
thp.tuv_tank_temp_c,
|
||||||
@@ -95,12 +145,12 @@ LEFT JOIN LATERAL (
|
|||||||
thp.cop_actual,
|
thp.cop_actual,
|
||||||
thp.defrost_active,
|
thp.defrost_active,
|
||||||
thp.alarm_code
|
thp.alarm_code
|
||||||
FROM ems.telemetry_heat_pump thp
|
from ems.telemetry_heat_pump thp
|
||||||
WHERE thp.heat_pump_id = hp.id
|
where thp.heat_pump_id = hp.id
|
||||||
ORDER BY thp.measured_at DESC
|
order by thp.measured_at desc
|
||||||
LIMIT 1
|
limit 1
|
||||||
) t ON true;
|
) t on true;
|
||||||
|
|
||||||
COMMENT ON VIEW ems.vw_latest_heat_pump IS
|
comment on view ems.vw_latest_heat_pump is
|
||||||
'Nejnovější telemetrická data pro každé tepelné čerpadlo včetně odhadovaného COP.
|
'Nejnovější telemetrická data pro každé tepelné čerpadlo včetně odhadovaného COP.
|
||||||
Slouží pro real-time dashboard a rozhodovací logiku plánování.';
|
Slouží pro real-time dashboard a rozhodovací logiku plánování.';
|
||||||
|
|||||||
Reference in New Issue
Block a user