Fix cpu thrashing during purge after all legacy events were removed (#89923)

* Fix cpu thrashing during purge after all legacy events were removed

We now remove the the index of of event ids on the states table when its
all NULLs to save space. The purge path needs to avoid checking for legacy
rows to purge if the index has been removed since it will result in a full
table scan each purge cycle that will always find no legacy rows to purge

* one more place

* drop the key constraint as well

* fixes

* more sqlite
This commit is contained in:
J. Nick Koston
2023-03-19 22:04:24 -04:00
committed by GitHub
parent 7f3e4cb3af
commit aebe4c66a6
5 changed files with 43 additions and 15 deletions
+13 -1
View File
@@ -10,7 +10,7 @@ from sqlalchemy.exc import DatabaseError, OperationalError
from sqlalchemy.orm.session import Session
from homeassistant.components import recorder
from homeassistant.components.recorder import Recorder
from homeassistant.components.recorder import Recorder, migration
from homeassistant.components.recorder.const import (
SQLITE_MAX_BIND_VARS,
SupportedDialect,
@@ -1726,6 +1726,18 @@ async def test_purge_can_mix_legacy_and_new_format(
) -> None:
"""Test purging with legacy a new events."""
instance = await async_setup_recorder_instance(hass)
await async_wait_recording_done(hass)
# New databases are no longer created with the legacy events index
assert instance.use_legacy_events_index is False
def _recreate_legacy_events_index():
"""Recreate the legacy events index since its no longer created on new instances."""
migration._create_index(instance.get_session, "states", "ix_states_event_id")
instance.use_legacy_events_index = True
await instance.async_add_executor_job(_recreate_legacy_events_index)
assert instance.use_legacy_events_index is True
utcnow = dt_util.utcnow()
eleven_days_ago = utcnow - timedelta(days=11)
with session_scope(hass=hass) as session:
@@ -142,6 +142,7 @@ async def test_migrate_times(
_get_states_index_names
)
states_index_names = {index["name"] for index in states_indexes}
assert recorder.get_instance(hass).use_legacy_events_index is True
await hass.async_stop()
await hass.async_block_till_done()
@@ -212,7 +213,12 @@ async def test_migrate_times(
)
states_index_names = {index["name"] for index in states_indexes}
assert "ix_states_event_id" not in states_index_names
# sqlite does not support dropping foreign keys so the
# ix_states_event_id index is not dropped in this case
# but use_legacy_events_index is still False
assert "ix_states_event_id" in states_index_names
assert recorder.get_instance(hass).use_legacy_events_index is False
await hass.async_stop()
dt_util.DEFAULT_TIME_ZONE = ORIG_TZ