Große recorder-Datenbank mit immer gleichen stati von SFML

Hi,

ich wollte heute mal herausfinden, warum meine HA-Backups so groß sind, und bin dann letztlich auf die home-assistant_v2.db gestossen, die auf der HAOS platte 5 gb in anspruch nimmt

-rw-r--r--    1 root     root        5.2G Sep  4 11:13 home-assistant_v2.db
-rw-r--r--    1 root     root       64.0K Sep  4 11:13 home-assistant_v2.db-shm
-rw-r--r--    1 root     root       17.3M Sep  4 11:13 home-assistant_v2.db-wal

und im komprimierten Backup dann ganz grob 3/4 der komprimierten Größe:

Also hab ich mich mit der Unterstützung von ChatGPT (sorry) auf die Suche gemacht.

Schritt 1: Welche Tabellen brauchen den Platz? AW: state_attributes

sqlite3 -readonly home-assistant_v2.db "
SELECT
  name,
  printf('%.2f GB', SUM(pgsize)/1024.0/1024/1024) AS size
FROM dbstat
GROUP BY name
ORDER BY SUM(pgsize) DESC;
"

╭────────────────────────────────────────────────┬─────────╮
│                      name                      │  size   │
╞════════════════════════════════════════════════╪═════════╡
│ state_attributes                               │ 2.31 GB │
│ states                                         │ 0.63 GB │
│ statistics                                     │ 0.29 GB │
│ ix_states_context_id_bin                       │ 0.21 GB │
│ ix_states_metadata_id_last_updated_ts          │ 0.16 GB │
│ ix_states_last_updated_ts                      │ 0.14 GB │

Schritt 2: Was in state_attributes braucht den Platz? AW: solar_forecast_energy_ai_* ganz vorn dabei

sqlite3 -readonly home-assistant_v2.db "
SELECT
  sm.entity_id,
  COUNT(*) AS states,
  COUNT(DISTINCT s.attributes_id) AS attribute_sets
FROM states s
JOIN states_meta sm ON s.metadata_id = sm.metadata_id
GROUP BY s.metadata_id
ORDER BY attribute_sets DESC
LIMIT 50;
"


╭───────────────────────────────────────────────────────────────────────────┬────────┬────────────────╮
│                                 entity_id                                 │ states │ attribute_sets │
╞═══════════════════════════════════════════════════════════════════════════╪════════╪════════════════╡
│ sensor.solar_forecast_ml_external_sensors_status                          │ 231158 │         213663 │
│ sensor.solar_forecast_energy_ai_wallbox_empfehlung                        │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_erklarung_der_wallbox_empfehlung          │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_vertrauen_der_wallbox_empfehlung          │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_wallbox_prognoseunsicherheit              │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_nachster_empfohlener_ladestart            │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_empfohlenes_ladeende                      │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_benotigte_ladeenergie                     │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_erwarteter_pv_ladeanteil                  │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_geschatzte_ladekosten                     │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_geschatzter_kostenvorteil_der_ladeplanung │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_abfahrtsbereitschaft                      │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_wallbox_datenqualitat                     │  90863 │          90863 │
│ binary_sensor.solar_forecast_energy_ai_wallbox_ladefenster_aktiv          │  90863 │          90863 │
│ binary_sensor.solar_forecast_energy_ai_pv_laden_empfohlen                 │  90863 │          90863 │
│ binary_sensor.solar_forecast_energy_ai_wallbox_rest_pv_fenster_aktiv      │  90863 │          90863 │
│ binary_sensor.solar_forecast_energy_ai_niedrigpreis_laden_empfohlen       │  90863 │          90863 │
│ binary_sensor.solar_forecast_energy_ai_abfahrtsziel_gefahrdet             │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_grund_der_wallbox_empfehlung              │  90863 │          90863 │
│ sensor.solar_forecast_energy_ai_lokaler_temperaturprognose_mae            │  50761 │          50744 │
│ sensor.solar_forecast_energy_ai_lokale_temperaturprognose_abweichung      │  50761 │          50744 │
│ binary_sensor.solar_forecast_stats_pv_surplus_available                   │  54639 │          43105 │
│ sensor.walli_laden_heute                                                  │  41182 │          41151 │
│ sensor.walli_laden_lfd_monat                                              │  41164 │          41142 │
│ sensor.walli_laden_lfd_woche                                              │  41164 │          41142 │
│ sensor.walli_laden_lfd_jahr                                               │  41162 │          41141 │
│ sensor.walli_laden_total                                                  │  41162 │          41141 │
│ sensor.solar_forecast_ml_sfml_total_actual_today                          │  34778 │          34768 │
│ sensor.solar_forecast_ml_sfml_total_yield_today                           │  34778 │          34768 │
│ sensor.solar_forecast_ml_gruppe_1_power                                   │  34778 │          34768 │
│ sensor.solar_forecast_ml_gruppe_1_actual_today                            │  34778 │          34768 │
│ sensor.solar_forecast_ml_gruppe_2_power                                   │  34778 │          34768 │
│ sensor.solar_forecast_ml_gruppe_2_actual_today                            │  34778 │          34768 │
│ sensor.solar_forecast_ml_sfml_total_power                                 │  34778 │          34768 │
│ sensor.wallbox_laden_tag                                                  │  20670 │          20618 │
│ sensor.wallbox_w                                                          │  20652 │          20517 │
│ sensor.wallbox_laden_m                                                    │  20652 │          20515 │
│ sensor.wallbox_laden_jahr                                                 │  20650 │          20433 │
│ sensor.wallbox_laden_total                                                │  20650 │          20433 │
│ sensor.octopus_tag_taglich                                                │  18034 │          18010 │
│ sensor.octopus_tag_monatlich                                              │  18016 │          18001 │
│ sensor.octopus_tag_jahrlich                                               │  18014 │          18000 │
│ sensor.octopus_netzbezug_tag_ab_01_05_2026                                │  18014 │          18000 │
│ sensor.stromeinspeisung_heute                                             │  11381 │          11354 │
│ sensor.strom_einspeisung_w                                                │  11363 │          11345 │
│ sensor.strom_einspeisung_m                                                │  11363 │          11345 │
│ sensor.strom_einspeisung_y                                                │  11361 │          11344 │
│ weather.luedenscheid                                                      │   8781 │           8776 │
│ sensor.stromverbrauch_heute                                               │   7081 │           7054 │
│ sensor.strom_netzbezug_w                                                  │   7063 │           7045 │
╰───────────────────────────────────────────────────────────────────────────┴────────┴────────────────╯

Schritt 3: Sind da Datensätze dupliziert? AW: Nein

sqlite3 -readonly home-assistant_v2.db "
SELECT
  COUNT(*) AS total_attribute_rows,
  COUNT(DISTINCT shared_attrs) AS unique_attribute_contents
FROM state_attributes;
"
╭──────────────────────┬──────────────────────╮
│ total_attribute_rows │ unique_attribute_... │
╞══════════════════════╪══════════════════════╡
│              2838644 │              2838644 │
╰──────────────────────┴──────────────────────╯

Schritt 4: Gibt es große Cluster? AW: es wird spannend

Grund hierfür: Vermutung: es gab zwischendurch einen Bug, denn zB solar_forecast_energy_ai_wallbox_empfehlung ändert sich vllt 5 mal pro Tag in der UI.

SELECT
  date(last_updated_ts, 'unixepoch') AS utc_day,
  COUNT(*) AS changes
FROM states s
JOIN states_meta sm ON s.metadata_id = sm.metadata_id
WHERE sm.entity_id = 'sensor.solar_forecast_energy_ai_wallbox_empfehlung'
GROUP BY utc_day
ORDER BY changes DESC
LIMIT 30;
"

╭────────────┬─────────╮
│  utc_day   │ changes │
╞════════════╪═════════╡
│ 2026-08-25 │   13717 │
│ 2026-08-30 │   11820 │
│ 2026-08-26 │   10194 │
│ 2026-08-29 │    9874 │
│ 2026-09-02 │    9379 │
│ 2026-09-01 │    8747 │
│ 2026-08-27 │    8514 │
│ 2026-09-03 │    7363 │
│ 2026-08-31 │    6342 │
│ 2026-08-28 │    3783 │
│ 2026-09-04 │    1140 │
╰────────────┴─────────╯

13717 Änderungen an einem Tag?

UI sieht nicht danach aus…

Schritt 5: Was ändert sich da eigentlich? AW: (fast) nichts

SELECT
  state,
  COUNT(*) AS changes
FROM states s
JOIN states_meta sm ON s.metadata_id = sm.metadata_id
WHERE sm.entity_id = 'sensor.solar_forecast_energy_ai_wallbox_empfehlung'
  AND last_updated_ts >= strftime('%s', '2026-08-25 11:00:00')
  AND last_updated_ts < strftime('%s', '2026-08-25 14:00:00')
GROUP BY state
ORDER BY changes DESC;
"

╭────────┬─────────╮
│ state  │ changes │
╞════════╪═════════╡
│ charge │    5903 │
│ defer  │     401 │
╰────────┴─────────╯

Verstehe ich so: wir schreiben tausende male den gleichen Wert rein.

Stichprobe: Was ändert sich zwischen zwei Werten? AW: intent_id

➜  /homeassistant sqlite3 -readonly home-assistant_v2.db "
WITH x AS (
  SELECT
    sa.shared_attrs,
    ROW_NUMBER() OVER (ORDER BY s.last_updated_ts) AS rn
  FROM states s
  JOIN states_meta sm ON s.metadata_id = sm.metadata_id
  JOIN state_attributes sa ON s.attributes_id = sa.attributes_id
  WHERE sm.entity_id = 'sensor.solar_forecast_energy_ai_wallbox_empfehlung'
    AND s.last_updated_ts >= strftime('%s', '2026-08-25 11:00:00')
    AND s.last_updated_ts < strftime('%s', '2026-08-25 14:00:00')
),
a AS (SELECT shared_attrs FROM x WHERE rn = 1),
b AS (SELECT shared_attrs FROM x WHERE rn = 2)

SELECT
  'A' AS record,
  key,
  value
FROM a, json_each(a.shared_attrs)

UNION ALL

SELECT
  'B' AS record,
  key,
  value
FROM b, json_each(b.shared_attrs)

ORDER BY key, record;
"

╭────────┬───────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ record │                key                │                                                                                                   value                                                                                                   │
╞════════╪═══════════════════════════════════╪═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡
│ A      │ advisory_only                     │                                                                                                                                                                                                         1 │
│ B      │ advisory_only                     │                                                                                                                                                                                                         1 │
│ A      │ allocation_origin                 │ stats_household_then_heat_pump_then_battery_then_calibration_reserve_then_wallbox_then_grid_export                                                                                                        │
│ B      │ allocation_origin                 │ stats_household_then_heat_pump_then_battery_then_calibration_reserve_then_wallbox_then_grid_export                                                                                                        │
│ A      │ battery_energy_demand_kwh         │                                                                                                                                                                                                      10.0 │
│ B      │ battery_energy_demand_kwh         │                                                                                                                                                                                                      10.0 │
│ A      │ charging_efficiency_percent       │                                                                                                                                                                                                        90 │
│ B      │ charging_efficiency_percent       │                                                                                                                                                                                                        90 │
│ A      │ control_services_called           │                                                                                                                                                                                                         0 │
│ B      │ control_services_called           │                                                                                                                                                                                                         0 │
│ A      │ demand_confidence_percent         │                                                                                                                                                                                                        95 │
│ B      │ demand_confidence_percent         │                                                                                                                                                                                                        95 │
│ A      │ demand_source                     │ soc                                                                                                                                                                                                       │
│ B      │ demand_source                     │ soc                                                                                                                                                                                                       │
│ A      │ departure_time                    │ 2026-08-26T05:00:00+00:00                                                                                                                                                                                 │
│ B      │ departure_time                    │ 2026-08-26T05:00:00+00:00                                                                                                                                                                                 │
│ A      │ device_class                      │ enum                                                                                                                                                                                                      │
│ B      │ device_class                      │ enum                                                                                                                                                                                                      │
│ A      │ explanation_evidence              │ ["Benötigte Wallbox-Energie 11.11 kWh bei 90 % Ladeeffizienz","Aus Fahrzeug-Ladezustand und Ziel 100 % berechnet","PV-Anteil 11.11 kWh, Prognoseband 11.11–11.11 kWh","Aktueller Strompreis 30.4 ct/kWh"] │
│ B      │ explanation_evidence              │ ["Benötigte Wallbox-Energie 11.11 kWh bei 90 % Ladeeffizienz","Aus Fahrzeug-Ladezustand und Ziel 100 % berechnet","PV-Anteil 11.11 kWh, Prognoseband 11.11–11.11 kWh","Aktueller Strompreis 30.4 ct/kWh"] │
│ A      │ explanation_headline              │ Jetzt verbleibenden PV-Überschuss nutzen                                                                                                                                                                  │
│ B      │ explanation_headline              │ Jetzt verbleibenden PV-Überschuss nutzen                                                                                                                                                                  │
│ A      │ forecast_uncertainty_percent      │                                                                                                                                                                                                        31 │
│ B      │ forecast_uncertainty_percent      │                                                                                                                                                                                                        31 │
│ A      │ friendly_name                     │ Solar Forecast Energy AI Wallbox-Empfehlung                                                                                                                                                               │
│ B      │ friendly_name                     │ Solar Forecast Energy AI Wallbox-Empfehlung                                                                                                                                                               │
│ A      │ intent_id                         │ 650fa5bdb972f840                                                                                                                                                                                          │
│ B      │ intent_id                         │ 5025270adddd4fa4                                                                                                                                                                                          │
│ A      │ master_enabled                    │                                                                                                                                                                                                         0 │
│ B      │ master_enabled                    │                                                                                                                                                                                                         0 │
│ A      │ passive_signal                    │                                                                                                                                                                                                         1 │
│ B      │ passive_signal                    │                                                                                                                                                                                                         1 │
│ A      │ reason                            │ pv_surplus                                                                                                                                                                                                │
│ B      │ reason                            │ pv_surplus                                                                                                                                                                                                │
│ A      │ recommendation_confidence_percent │                                                                                                                                                                                                        56 │
│ B      │ recommendation_confidence_percent │                                                                                                                                                                                                        56 │
│ A      │ valid_until                       │ 2026-08-25T15:00:00+00:00                                                                                                                                                                                 │
│ B      │ valid_until                       │ 2026-08-25T15:00:00+00:00                                                                                                                                                                                 │
╰────────┴───────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Eigentliche Frage(n)

Warum sehen wir so viele Schreibvorgänge, könnte man das evtl. deduplizieren, oder braucht SFML die unterschiedlichen Einträge? Und ist das überhaupt mit dem recorder switch noch notwendig, oder kann ich die DB purgen und es sammelt sich nicht wieder an?

Ohne jetzt alle states durchgeschaut zu haben, anhand der gleichen Counts kriege ich das Gefühl, dass das insgesamt ein Muster ist, also nicht nur für die Wallbox Empfehlung passiert.

Ich könnte jetzt natürlich auch für die backups sowas wie AI Empfehlung weglassen, aber so richtig zufriedenstellend finde ich das nicht. Sorry für den ganzen AI-Content.

Liebe Grüße
nightrunner sein Informatikersohn

Du kannst ALLE SFML Sensoren vom Recorder ausschließen die Du nicht benötigst! Das ist der einfachste Weg.. und die gängige Praxis in dem HA Kosmos für alle Sensoren die man nicht nachhalten möchte, ein BUG ist es nicht.. sondern eher eine Eigenart von HA das er prinzipiell alles in die DB schreibt, sofern man es nicht ausklammert.

Zara