La sobriete numerique est un levier a la fois economique et environnemental. La regle d’or: mesurer d’abord, agir ensuite. Sans metrologie fiable, on optimise a l’aveugle. Avec des mesures simples et reproductibles (kWh, cout, volumes), on priorise les gros postes et on documente les gains. Cette page propose un cadre concret: instrumentation minimale, requetes utiles, leviers d’optimisation et arbitrages “valeur x kWh”.
prerequis
- une base de metrologie (meme simple) pour stocker energie, volumes et couts.
- des etiquettes par job/requete (owner, produit, fonctionnalite) pour agreger au bon niveau.
- un facteur carbone par region ou datacenter (gCO2e/kWh) pour estimer l’empreinte.
- un cycle d’amelioration continue (revue mensuelle, top 3 postes).
apercu rapide
- instrumenter compute, stockage, transferts avec des schemas stables.
- exposer des tableaux de bord par produit et par fonctionnalite.
- cibler les 3 postes majeurs, pas les micro-optimisations.
- appliquer des leviers simples: formats columnaires, compression, caches, TTL.
- industrialiser les arrets planifies et la mise en veille des ressources.
- rendre visibles les couts et les kWh aux equipes pour guider les choix.
cartographier les postes d’empreinte
modeles de donnees pour mesurer
tables minimales
-- energie et cout par job (horodatage et etiquette produit/feature)
CREATE TABLE IF NOT EXISTS finops_energy (
ts TIMESTAMP NOT NULL,
job TEXT NOT NULL,
product TEXT NOT NULL,
feature TEXT NOT NULL,
kwh DOUBLE PRECISION NOT NULL,
cost_eur DOUBLE PRECISION NOT NULL,
region TEXT,
carbon_intensity_g_per_kwh DOUBLE PRECISION DEFAULT 400
);
-- transferts reseau sortants (egress)
CREATE TABLE IF NOT EXISTS finops_transfer (
ts TIMESTAMP NOT NULL,
flow TEXT NOT NULL,
product TEXT NOT NULL,
feature TEXT NOT NULL,
gb DOUBLE PRECISION NOT NULL,
cost_eur DOUBLE PRECISION NOT NULL,
region TEXT
);
-- stockage par classe (chaud/tiède/froid) et par produit
CREATE TABLE IF NOT EXISTS finops_storage (
day DATE NOT NULL,
product TEXT NOT NULL,
feature TEXT NOT NULL,
class TEXT CHECK (class IN ('hot','warm','cold')),
tib DOUBLE PRECISION NOT NULL,
cost_eur DOUBLE PRECISION NOT NULL,
region TEXT
);
etiquetage: discipline utile
-- exemple d'etiquettes au lancement d'un job ETL
INSERT INTO finops_energy(ts, job, product, feature, kwh, cost_eur, region, carbon_intensity_g_per_kwh)
VALUES (NOW(), 'daily_orders_etl', 'commerce', 'orders', 12.4, 2.90, 'eu-west', 300);
mesurer: requetes pratiques
- energie et cout par job et sur 30 jours
- empreinte carbone associee (kgCO2e)
- cout par utilisateur et par fonctionnalite
- transferts sortants a surveiller
-- top jobs par kWh sur 30 jours
SELECT job,
ROUND(SUM(kwh), 2) AS kwh,
ROUND(SUM(cost_eur), 2) AS cost
FROM finops_energy
WHERE ts >= CURRENT_DATE - INTERVAL '30 day'
GROUP BY job
ORDER BY kwh DESC
LIMIT 20;
-- estimation kgCO2e par produit
SELECT product,
ROUND(SUM(kwh * carbon_intensity_g_per_kwh) / 1000.0, 1) AS kgco2e,
ROUND(SUM(cost_eur), 2) AS cost
FROM finops_energy
WHERE ts >= CURRENT_DATE - INTERVAL '30 day'
GROUP BY product
ORDER BY kgco2e DESC;
-- cout par fonctionnalite (energy + transfer + storage)
WITH e AS (
SELECT product, feature, SUM(cost_eur) AS c FROM finops_energy
WHERE ts >= CURRENT_DATE - INTERVAL '30 day' GROUP BY 1,2
),
t AS (
SELECT product, feature, SUM(cost_eur) AS c FROM finops_transfer
WHERE ts >= CURRENT_DATE - INTERVAL '30 day' GROUP BY 1,2
),
s AS (
SELECT product, feature, SUM(cost_eur) AS c FROM finops_storage
WHERE day >= CURRENT_DATE - INTERVAL '30 day' GROUP BY 1,2
)
SELECT COALESCE(e.product,t.product,s.product) AS product,
COALESCE(e.feature,t.feature,s.feature) AS feature,
ROUND(COALESCE(e.c,0)+COALESCE(t.c,0)+COALESCE(s.c,0),2) AS cost_30d_eur
FROM e FULL OUTER JOIN t USING(product,feature)
FULL OUTER JOIN s USING(product,feature)
ORDER BY cost_30d_eur DESC
LIMIT 20;
-- transferts sortants eleves (egress)
SELECT flow, product, feature,
ROUND(SUM(gb),1) AS gb_30d, ROUND(SUM(cost_eur),2) AS cost_30d_eur
FROM finops_transfer
WHERE ts >= CURRENT_DATE - INTERVAL '30 day'
GROUP BY flow, product, feature
ORDER BY gb_30d DESC
LIMIT 20;
reduire: leviers concrets
- formats columnaires et compression (parquet, orc) pour les tables analytiques.
- vues aggregees et caches pour les requetes repetitives.
- modeles plus petits (distilles, quantifies) pour l’inference.
- arrets planifies et mises en veille automatiques des ressources.
- retention et TTL adaptes: purger ce qui ne sert plus.
# exemples generiques (pseudo)
# compression logs applicatifs
rotate_logs --gzip --max-age 14d
# purge donnees temporaires > 7 jours
delete_old --path s3://data/tmp --older-than 7d
# plan d'extinction hors heures pleines
schedule_shutdown --group etl-workers --weekdays 20:00-06:00 --weekends all
activer des caches et des vues aggregees
-- vue aggregee pour un tableau de bord tres consomme
CREATE MATERIALIZED VIEW IF NOT EXISTS bi.orders_daily AS
SELECT order_date::date AS d, country, COUNT(*) AS n, SUM(amount_eur) AS revenue
FROM raw.orders
WHERE order_date >= CURRENT_DATE - INTERVAL '180 day'
GROUP BY 1,2;
-- rafraichissement planifie
-- (utiliser le planificateur de votre SGBD ou un orchestrateur)
REFRESH MATERIALIZED VIEW bi.orders_daily;
quantifier et distiller les modeles
# estimation simple du gain de cout vs latence
def gain(lat_ms_before, lat_ms_after, cpu_w_before, cpu_w_after, qps):
# kWh par heure ~ (W * h) / 1000 ; ici on compare puissance approx
before = cpu_w_before * qps * lat_ms_before / 1000.0
after = cpu_w_after * qps * lat_ms_after / 1000.0
return {"delta_power_w_ms": before - after, "improvement_pct": 100.0 * (before - after) / max(before, 1e-9)}
arbitrer: valeur x kWh
- matrice “valeur vs kWh”: prioriser ce qui consomme beaucoup et apporte peu.
- exiger une preuve de valeur avant d’allouer davantage de ressources.
- rendre visibles couts et kWh aux equipes: ownership et responsabilite.
gabarit de fiche “valeur x kWh”
feature: "recalcul dashboard temps reel"
benefice_attendu: "latence -50% pour 120 utilisateurs"
cout_30j_eur: 3200
kwh_30j: 950
kgco2e_30j: 280
leviers_testes:
- "cache 5 min" : gain "kwh -35%, latence P95 -40%"
- "agregations horaire" : gain "kwh -50%, latence P95 -55%"
decision: "deployer agregations horaire, revoir besoin temps reel"
owner: "@bi-team"
revue: "mois prochain"
tutoriel pas-a-pas
etape 1: instrumenter
- collecter kWh et couts par job.
- enregistrer transferts et stockage par produit/feature.
- associer un facteur carbone par region.
-- exemple: enrichir chaque ligne d'energie avec un facteur carbone
UPDATE finops_energy
SET carbon_intensity_g_per_kwh = 300
WHERE region = 'eu-west';
etape 2: etiqueter
- imposer product et feature sur tous les jobs et pipelines.
- refuser l’execution si les etiquettes sont absentes.
# pseudo hook d'orchestrateur
[ -z "$PRODUCT" ] && echo "PRODUCT manquant" && exit 1
[ -z "$FEATURE" ] && echo "FEATURE manquant" && exit 1
etape 3: analyser et prioriser
- sortir les top 20 consommateurs.
- qualifier valeur metier vs cout/empreinte.
-- top consommateurs par feature
SELECT product, feature, ROUND(SUM(kwh),1) AS kwh_30d, ROUND(SUM(cost_eur),2) AS cost_30d
FROM finops_energy
WHERE ts >= CURRENT_DATE - INTERVAL '30 day'
GROUP BY 1,2
ORDER BY kwh_30d DESC
LIMIT 20;
etape 4: agir
- appliquer formats columnaires, compression, vues aggregees.
- reduire la resolution des donnees si la precision est surabondante.
- rationaliser les exports repetitifs (regrouper, dedupliquer).
-- exemple: echantillonnage raisonnable pour exploration
CREATE TABLE IF NOT EXISTS raw.events_sampled AS
SELECT * FROM raw.events
WHERE random() < 0.1;
etape 5: verifier et documenter les gains
- comparer kWh et latence avant/apres.
- consigner les changements et les preuves.
change_log:
id: "opt-2024-11-dashboard_orders"
before:
kwh_30d: 950
p95_ms: 1800
after:
kwh_30d: 520
p95_ms: 940
decision: "generalisation"
owner: "@bi-team"
exemples complets
cas 1: passer de json a parquet
-- table de travail json brute
CREATE TABLE raw.events_json AS
SELECT *
FROM external_raw_json; -- source externe en json
-- table columnnaire (parquet) avec compression
CREATE TABLE raw.events_parquet
WITH (storage_format = 'parquet', compression = 'snappy') AS
SELECT *
FROM raw.events_json;
-- gain attendu: IO reduit, scans plus rapides, kWh en baisse
cas 2: TTL et retentions
-- table partitionnee par jour avec retention sur 90 jours pour le chaud
CREATE TABLE IF NOT EXISTS logs.app_events (
day DATE,
ts TIMESTAMP,
user_id TEXT,
event TEXT,
payload JSONB
) PARTITION BY RANGE (day);
-- politique de purge (adaptation selon SGBD)
-- supprimer partitions > 90 jours
-- a programmer via un job planifie
cas 3: choisir un modele compact
# selection simple selon budget latence et memoire
candidats = [
{"name": "model_large_fp32", "lat_ms": 60, "mem_mb": 1200, "acc": 0.92},
{"name": "model_small_int8", "lat_ms": 18, "mem_mb": 180, "acc": 0.90}
]
def choix(cands, lat_budget=20, mem_budget=256):
c = [m for m in cands if m["lat_ms"] <= lat_budget and m["mem_mb"] <= mem_budget]
return max(c, key=lambda m: m["acc"]) if c else min(cands, key=lambda m: m["lat_ms"])
suivi et transparence
- publier un tableau de bord “carbone et couts” par produit.
- suivre delai de resolution des optimisations et gains reels observes.
- partager les bonnes pratiques et les gabarits internes.
dashboard_kpis:
top3_kwh_features: ["orders_dash", "clickhouse_backup", "daily_etl"]
kwh_30d_total: 4200
kgco2e_30d_total: 1260
storage_cold_tib: 72
egress_gb_30d: 3800
pieges et parades
- optimisation micro -> faible gain -> choisir top 3 postes, mesurer avant/apres.
- absence de mesures -> slogans -> instrumenter d’abord, arbitrer ensuite.
- vues non rafraichies -> incoherence -> planifier refresh et invalider caches.
- jobs orphelins -> cout caché -> etiqueter, desactiver par defaut, revue mensuelle.
- precisions excessives -> IO inutiles -> agreger au besoin, adapter la resolution.
faq
-
Comment estimer l’empreinte carbone si je n’ai que des kWh ? Multipliez les kWh par un facteur carbone de votre region (gCO2e/kWh). Conservez la methode et les facteurs utilises dans vos rapports.
-
Quelles optimisations donnent souvent les meilleurs gains ? Passer en formats columnaires avec compression, materialiser les agregats critiques, et supprimer les exports repetitifs sont des gains rapides.
-
Faut il viser une precision de mesure parfaite avant d’agir ? Non. Une metrologie simple suffit pour identifier les gros postes. Affinez ensuite.
-
Comment eviter de casser la valeur metier en optimisant ? Demandez une preuve de valeur. Si la precision temps reel n’apporte pas de benefice mesure, revenez a une frequence plus sobre.
-
Qui doit piloter ces sujets ? Chaque equipe produit pour son perimetre, avec un support central finops/sobriete qui fournit schemas, outils et benchmarks internes.