FEAT : conf objets timescale OK
This commit is contained in:
parent
6f5293d325
commit
aaa63a4a8d
141
notes.md
141
notes.md
@ -14,53 +14,9 @@ exit
|
||||
cd /tmp
|
||||
scp grab-4:/tmp/backup_postgres.dump .
|
||||
pg_restore -c -x -t mesure -d postgres -h localhost -U postgres -W backup_postgres.dump
|
||||
pg_restore -c -x -I mesure_idx1 -d postgres -h localhost -U postgres -W backup_postgres.dump
|
||||
pg_restore -c -x -I mesure_idx2 -d postgres -h localhost -U postgres -W backup_postgres.dump
|
||||
```
|
||||
|
||||
### Création d'une hypertable
|
||||
|
||||
```sql
|
||||
CREATE TABLE mesure_ng (
|
||||
"date" TIMESTAMPTZ,
|
||||
id_captation INT NOT NULL,
|
||||
valeur float4 NOT NULL
|
||||
) WITH (
|
||||
tsdb.hypertable,
|
||||
timescaledb.segmentby = 'id_captation',
|
||||
timescaledb.orderby='date DESC'
|
||||
)
|
||||
|
||||
INSERT INTO mesure_ng ("date", id_captation, valeur)
|
||||
SELECT "date", id_captation, valeur
|
||||
FROM mesure
|
||||
```
|
||||
|
||||
### Compression des données (stockage en colonnes)
|
||||
|
||||
`SELECT add_columnstore_policy('mesure_ng', INTERVAL '15 days')`
|
||||
|
||||
|
||||
### Ex. de requête
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
time_bucket('1 hour', "date") AS heure,
|
||||
round(
|
||||
average(
|
||||
time_weight('linear', "date", valeur)
|
||||
)
|
||||
) AS moyenne_conso,
|
||||
COUNT(*) AS nombre_de_mesures
|
||||
FROM
|
||||
mesure_ng
|
||||
WHERE
|
||||
"date" BETWEEN '2026-03-01 00:00:00' AND '2026-03-31 23:59:59'
|
||||
and id_captation = 59 -- puissance PAC
|
||||
GROUP BY
|
||||
heure
|
||||
ORDER BY
|
||||
heure;
|
||||
# pg_restore -c -x -I mesure_idx1 -d postgres -h localhost -U postgres -W backup_postgres.dump
|
||||
# pg_restore -c -x -I mesure_idx2 -d postgres -h localhost -U postgres -W backup_postgres.dump
|
||||
pg_restore -c -x -t captation -d postgres -h localhost -U postgres -W backup_postgres.dump
|
||||
```
|
||||
|
||||
### Exploit
|
||||
@ -73,40 +29,73 @@ WHERE hypertable_name = 'mesure_ng'
|
||||
|
||||
`SELECT * FROM timescaledb_information.jobs`
|
||||
|
||||
### Continuous aggregates (WIP)
|
||||
### WIP
|
||||
|
||||
<https://www.tigerdata.com/docs/use-timescale/latest/continuous-aggregates/create-a-continuous-aggregate>
|
||||
#### Grafana
|
||||
|
||||
* CREATE MATERIALIZED VIEW
|
||||
* CALL add_continuous_aggregate_policy
|
||||
* supprimer les "vieilles" données de mesure_ng (add_retention_policy ?)
|
||||
mixe de
|
||||
|
||||
#### Exemples
|
||||
sur le range :
|
||||
|
||||
##### Gauges
|
||||
|
||||
CREATE MATERIALIZED VIEW sensor_hourly
|
||||
WITH (timescaledb.continuous)
|
||||
AS
|
||||
SELECT
|
||||
time_bucket('1 hour', time) AS bucket,
|
||||
sensor_id,
|
||||
average(
|
||||
time_weight('linear', "date", valeur)
|
||||
) AS moyenne_temporelle,
|
||||
percentile_agg(value) AS pct
|
||||
FROM sensor_data
|
||||
GROUP BY bucket, sensor_id;
|
||||
|
||||
Puis
|
||||
```sql
|
||||
SELECT *
|
||||
FROM (
|
||||
|
||||
SELECT
|
||||
bucket,
|
||||
sensor_id,
|
||||
approx_percentile(0.95, pct) AS p95,
|
||||
approx_percentile(0.99, pct) AS p99
|
||||
FROM sensor_hourly;
|
||||
"date" AS time,
|
||||
valeur
|
||||
FROM mesure_gauge
|
||||
WHERE $__timeFilter("date")
|
||||
AND $__range_s < 86400
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
"date" AS time,
|
||||
average(valeur_temporelle)
|
||||
FROM mesure_gauge_heure
|
||||
WHERE $__timeFilter("date")
|
||||
AND $__range_s BETWEEN 86400 AND 2592000
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
"date" AS time,
|
||||
average(valeur_temporelle)
|
||||
FROM mesure_gauge_jour
|
||||
WHERE $__timeFilter("date")
|
||||
AND $__range_s > 2592000
|
||||
|
||||
) t
|
||||
ORDER BY time
|
||||
```
|
||||
|
||||
et où est dans le passé
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
FROM (
|
||||
|
||||
-- données récentes → brut
|
||||
SELECT
|
||||
mg."date" AS time,
|
||||
mg.valeur
|
||||
FROM mesure_gauge mg
|
||||
WHERE $__timeFilter(mg."date")
|
||||
AND $__to > now() - interval '7 days'
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- données anciennes → agrégées
|
||||
SELECT
|
||||
mgh."date" AS time,
|
||||
average(mgh.valeur_temporelle) AS valeur
|
||||
FROM mesure_gauge_heure mgh
|
||||
WHERE $__timeFilter(mgh."date")
|
||||
AND $__to <= now() - interval '7 days'
|
||||
|
||||
) t
|
||||
ORDER BY time;
|
||||
```
|
||||
|
||||
##### Index
|
||||
|
||||
delta(counter_agg(time, value))
|
||||
3
sql/1_type_captation.sql
Normal file
3
sql/1_type_captation.sql
Normal file
@ -0,0 +1,3 @@
|
||||
-- pour différencier les capteurs (Gauges) des index (Compteurs)
|
||||
ALTER TABLE public.captation ADD "type" varchar DEFAULT 'G' NOT NULL;
|
||||
COMMENT ON COLUMN public.captation."type" IS 'G pour Gauge, C pour Compteur (index)';
|
||||
71
sql/2_gauge.sql
Normal file
71
sql/2_gauge.sql
Normal file
@ -0,0 +1,71 @@
|
||||
CREATE TABLE mesure_gauge ( -- TODO ; revoir précudes d'injection de données pour faire la différence entre gauge et compteur
|
||||
"date" TIMESTAMPTZ,
|
||||
id_captation INT NOT NULL,
|
||||
valeur float4 NOT NULL
|
||||
) WITH (
|
||||
tsdb.hypertable,
|
||||
timescaledb.segmentby = 'id_captation',
|
||||
timescaledb.orderby='date DESC'
|
||||
);
|
||||
|
||||
INSERT INTO mesure_gauge ("date", id_captation, valeur)
|
||||
SELECT m."date", m.id_captation, m.valeur
|
||||
FROM mesure m
|
||||
WHERE m.id_captation IN (
|
||||
SELECT c.id_captation
|
||||
FROM captation c
|
||||
WHERE c."type" = 'G' -- TODO : prévoir cette info dans captation
|
||||
);
|
||||
|
||||
SELECT add_retention_policy('mesure_gauge', INTERVAL '6 months'); -- on ne garde les données brutes que 6 mois
|
||||
|
||||
CREATE MATERIALIZED VIEW mesure_gauge_heure -- valeurs par heure
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT
|
||||
id_captation,
|
||||
time_bucket(INTERVAL '1 HOUR', mg."date") AS "date",
|
||||
time_weight('linear', mg."date", mg.valeur) AS valeur_temporelle,
|
||||
MAX(mg.valeur),
|
||||
MIN(mg.valeur)
|
||||
FROM mesure_gauge mg
|
||||
GROUP BY id_captation, time_bucket(INTERVAL '1 hour', mg."date");
|
||||
|
||||
SELECT add_continuous_aggregate_policy( -- On met à jour les données tt les h en relisant les données brutes entre 1 mois et 1 jour
|
||||
'mesure_gauge_heure',
|
||||
start_offset => INTERVAL '1 month',
|
||||
end_offset => INTERVAL '1 day',
|
||||
schedule_interval => INTERVAL '1 hour'
|
||||
);
|
||||
|
||||
SELECT add_retention_policy('mesure_gauge_heure', INTERVAL '5 years'); -- on ne garde les données par h que 5 ans
|
||||
|
||||
CREATE MATERIALIZED VIEW mesure_gauge_jour -- valeurs par jour
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT
|
||||
id_captation,
|
||||
time_bucket(INTERVAL '1 DAY', mg."date") AS "date",
|
||||
rollup(valeur_temporelle) AS valeur_temporelle,
|
||||
MAX(mg.max),
|
||||
MIN(mg.min)
|
||||
FROM mesure_gauge_heure mg
|
||||
GROUP BY id_captation, time_bucket(INTERVAL '1 DAY', mg."date");
|
||||
|
||||
SELECT add_continuous_aggregate_policy( -- On met à jour les données tt les h en relisant les données brutes entre 1 mois et 1 jour
|
||||
'mesure_gauge_jour',
|
||||
start_offset => INTERVAL '1 month',
|
||||
end_offset => INTERVAL '1 day',
|
||||
schedule_interval => INTERVAL '1 hour'
|
||||
);
|
||||
|
||||
SELECT add_retention_policy('mesure_gauge_jour', INTERVAL '20 years'); -- on ne garde les données par h que 20 ans
|
||||
|
||||
-- ex. select
|
||||
select
|
||||
mgh.id_captation,
|
||||
time_bucket(INTERVAL '1 DAY', mgh."date") AS "date", -- 1 jour et pas seulement une heure
|
||||
average(rollup(valeur_temporelle)) AS moyenne -- rollup pour avour le concaténation des valeur_temporelle
|
||||
from mesure_gauge_heure mgh
|
||||
where mgh.id_captation = 59 -- puissance PAC
|
||||
group by mgh.id_captation, time_bucket(INTERVAL '1 DAY', mgh."date")
|
||||
order by "date" desc
|
||||
limit 1000;
|
||||
70
sql/3_compteur.sql
Normal file
70
sql/3_compteur.sql
Normal file
@ -0,0 +1,70 @@
|
||||
CREATE TABLE mesure_compteur ( -- TODO ; revoir précudes d'injection de données pour faire la différence entre gauge et compteur
|
||||
"date" TIMESTAMPTZ,
|
||||
id_captation INT NOT NULL,
|
||||
valeur float4 NOT NULL
|
||||
) WITH (
|
||||
tsdb.hypertable,
|
||||
timescaledb.segmentby = 'id_captation',
|
||||
timescaledb.orderby='date DESC'
|
||||
);
|
||||
|
||||
INSERT INTO mesure_compteur ("date", id_captation, valeur)
|
||||
SELECT m."date", m.id_captation, m.valeur
|
||||
FROM mesure m
|
||||
WHERE m.id_captation IN (
|
||||
SELECT c.id_captation
|
||||
FROM captation c
|
||||
WHERE c."type" = 'C' -- TODO : prévoir cette info dans captation
|
||||
);
|
||||
|
||||
SELECT add_retention_policy('mesure_compteur', INTERVAL '6 months'); -- on ne garde les données brutes que 6 mois
|
||||
|
||||
CREATE MATERIALIZED VIEW mesure_compteur_heure -- valeurs par heure
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT
|
||||
id_captation,
|
||||
time_bucket(INTERVAL '1 hour', mc."date") AS "date",
|
||||
counter_agg(mc."date", mc.valeur) AS valeur_temporelle
|
||||
FROM mesure_compteur mc
|
||||
GROUP BY
|
||||
id_captation,
|
||||
time_bucket(INTERVAL '1 hour', mc."date");
|
||||
|
||||
SELECT add_continuous_aggregate_policy('mesure_compteur_heure', -- On met à jour les données tt les h en relisant les données brutes entre 1 mois et 1 jour
|
||||
start_offset => INTERVAL '1 month',
|
||||
end_offset => INTERVAL '1 day',
|
||||
schedule_interval => INTERVAL '1 hour');
|
||||
|
||||
SELECT add_retention_policy('mesure_compteur_heure', INTERVAL '5 years'); -- on ne garde les données par h que 5 ans
|
||||
|
||||
CREATE MATERIALIZED VIEW mesure_compteur_jour -- valeurs par jour
|
||||
WITH (timescaledb.continuous) AS
|
||||
SELECT
|
||||
id_captation,
|
||||
time_bucket(INTERVAL '1 DAY', mg."date") AS "date",
|
||||
rollup(valeur_temporelle) AS valeur_temporelle
|
||||
FROM mesure_compteur_heure mg
|
||||
GROUP BY id_captation, time_bucket(INTERVAL '1 DAY', mg."date");
|
||||
|
||||
SELECT add_continuous_aggregate_policy( -- On met à jour les données tt les h en relisant les données brutes entre 1 mois et 1 jour
|
||||
'mesure_compteur_jour',
|
||||
start_offset => INTERVAL '1 month',
|
||||
end_offset => INTERVAL '1 day',
|
||||
schedule_interval => INTERVAL '1 hour'
|
||||
);
|
||||
|
||||
SELECT add_retention_policy('mesure_compteur_jour', INTERVAL '20 years'); -- on ne garde les données par h que 20 ans
|
||||
|
||||
-- ex. select
|
||||
SELECT
|
||||
mch.id_captation,
|
||||
time_bucket(INTERVAL '1 DAY', mch."date") AS "date", -- 1 jour et pas seulement une heure
|
||||
delta(rollup(mch.valeur_temporelle)) AS consommation,
|
||||
rate(rollup(mch.valeur_temporelle)) * 3600 AS debit_moyen,
|
||||
irate_left(rollup(mch.valeur_temporelle)) * 3600 AS debit_instantane,
|
||||
first_val(rollup(mch.valeur_temporelle)) AS index_debut,
|
||||
last_val(rollup(mch.valeur_temporelle)) AS index_fin
|
||||
FROM mesure_compteur_heure mch
|
||||
where mch.id_captation = 89 -- HP
|
||||
group by mch.id_captation, time_bucket(INTERVAL '1 DAY', mch."date")
|
||||
order by "date" desc
|
||||
7
sql/4_drop.sql
Normal file
7
sql/4_drop.sql
Normal file
@ -0,0 +1,7 @@
|
||||
DROP MATERIALIZED VIEW IF EXISTS mesure_gauge_jour;
|
||||
DROP MATERIALIZED VIEW IF EXISTS mesure_gauge_heure;
|
||||
DROP TABLE IF EXISTS mesure_gauge;
|
||||
|
||||
DROP MATERIALIZED VIEW IF EXISTS mesure_compteur_jour;
|
||||
DROP MATERIALIZED VIEW IF EXISTS mesure_compteur_jour;
|
||||
DROP TABLE IF EXISTS mesure_compteur;
|
||||
Loading…
Reference in New Issue
Block a user