mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Use cache to lookup event type ids in logbook (#91576)
noticed we can speed this up while looking at https://github.com/home-assistant/core/issues/91514 Note: this will not fix that issue as there is more going on there
This commit is contained in:
parent
f96515b90a
commit
2530031454
@ -14,6 +14,7 @@ from homeassistant.components.recorder import get_instance
|
||||
from homeassistant.components.recorder.filters import Filters
|
||||
from homeassistant.components.recorder.models import (
|
||||
bytes_to_uuid_hex_or_none,
|
||||
extract_event_type_ids,
|
||||
extract_metadata_ids,
|
||||
process_datetime_to_timestamp,
|
||||
process_timestamp_to_utc_isoformat,
|
||||
@ -153,17 +154,22 @@ class EventProcessor:
|
||||
|
||||
with session_scope(hass=self.hass, read_only=True) as session:
|
||||
metadata_ids: list[int] | None = None
|
||||
if self.entity_ids:
|
||||
instance = get_instance(self.hass)
|
||||
if self.entity_ids:
|
||||
metadata_ids = extract_metadata_ids(
|
||||
instance.states_meta_manager.get_many(
|
||||
self.entity_ids, session, False
|
||||
)
|
||||
)
|
||||
event_type_ids = tuple(
|
||||
extract_event_type_ids(
|
||||
instance.event_type_manager.get_many(self.event_types, session)
|
||||
)
|
||||
)
|
||||
stmt = statement_for_request(
|
||||
start_day,
|
||||
end_day,
|
||||
self.event_types,
|
||||
event_type_ids,
|
||||
self.entity_ids,
|
||||
metadata_ids,
|
||||
self.device_ids,
|
||||
|
@ -20,7 +20,7 @@ from .entities_and_devices import entities_devices_stmt
|
||||
def statement_for_request(
|
||||
start_day_dt: dt,
|
||||
end_day_dt: dt,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
entity_ids: list[str] | None = None,
|
||||
states_metadata_ids: Collection[int] | None = None,
|
||||
device_ids: list[str] | None = None,
|
||||
@ -37,7 +37,7 @@ def statement_for_request(
|
||||
return all_stmt(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
filters,
|
||||
context_id_bin,
|
||||
)
|
||||
@ -52,7 +52,7 @@ def statement_for_request(
|
||||
return entities_devices_stmt(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
states_metadata_ids or [],
|
||||
[json_dumps(entity_id) for entity_id in entity_ids],
|
||||
[json_dumps(device_id) for device_id in device_ids],
|
||||
@ -63,7 +63,7 @@ def statement_for_request(
|
||||
return entities_stmt(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
states_metadata_ids or [],
|
||||
[json_dumps(entity_id) for entity_id in entity_ids],
|
||||
)
|
||||
@ -73,6 +73,6 @@ def statement_for_request(
|
||||
return devices_stmt(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
[json_dumps(device_id) for device_id in device_ids],
|
||||
)
|
||||
|
@ -18,13 +18,13 @@ from .common import apply_states_filters, select_events_without_states, select_s
|
||||
def all_stmt(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
filters: Filters | None,
|
||||
context_id_bin: bytes | None = None,
|
||||
) -> StatementLambdaElement:
|
||||
"""Generate a logbook query for all entities."""
|
||||
stmt = lambda_stmt(
|
||||
lambda: select_events_without_states(start_day, end_day, event_types)
|
||||
lambda: select_events_without_states(start_day, end_day, event_type_ids)
|
||||
)
|
||||
if context_id_bin is not None:
|
||||
stmt += lambda s: s.where(Events.context_id_bin == context_id_bin).union_all(
|
||||
|
@ -23,7 +23,6 @@ from homeassistant.components.recorder.db_schema import (
|
||||
StatesMeta,
|
||||
)
|
||||
from homeassistant.components.recorder.filters import like_domain_matchers
|
||||
from homeassistant.components.recorder.queries import select_event_type_ids
|
||||
|
||||
from ..const import ALWAYS_CONTINUOUS_DOMAINS, CONDITIONALLY_CONTINUOUS_DOMAINS
|
||||
|
||||
@ -112,13 +111,13 @@ NOT_CONTEXT_ONLY = literal(value=None, type_=sqlalchemy.String).label("context_o
|
||||
def select_events_context_id_subquery(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
) -> Select:
|
||||
"""Generate the select for a context_id subquery."""
|
||||
return (
|
||||
select(Events.context_id_bin)
|
||||
.where((Events.time_fired_ts > start_day) & (Events.time_fired_ts < end_day))
|
||||
.where(Events.event_type_id.in_(select_event_type_ids(event_types)))
|
||||
.where(Events.event_type_id.in_(event_type_ids))
|
||||
.outerjoin(EventTypes, (Events.event_type_id == EventTypes.event_type_id))
|
||||
.outerjoin(EventData, (Events.data_id == EventData.data_id))
|
||||
)
|
||||
@ -145,13 +144,13 @@ def select_states_context_only() -> Select:
|
||||
|
||||
|
||||
def select_events_without_states(
|
||||
start_day: float, end_day: float, event_types: tuple[str, ...]
|
||||
start_day: float, end_day: float, event_type_ids: tuple[int, ...]
|
||||
) -> Select:
|
||||
"""Generate an events select that does not join states."""
|
||||
return (
|
||||
select(*EVENT_ROWS_NO_STATES, NOT_CONTEXT_ONLY)
|
||||
.where((Events.time_fired_ts > start_day) & (Events.time_fired_ts < end_day))
|
||||
.where(Events.event_type_id.in_(select_event_type_ids(event_types)))
|
||||
.where(Events.event_type_id.in_(event_type_ids))
|
||||
.outerjoin(EventTypes, (Events.event_type_id == EventTypes.event_type_id))
|
||||
.outerjoin(EventData, (Events.data_id == EventData.data_id))
|
||||
)
|
||||
|
@ -31,12 +31,12 @@ from .common import (
|
||||
def _select_device_id_context_ids_sub_query(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
json_quotable_device_ids: list[str],
|
||||
) -> Select:
|
||||
"""Generate a subquery to find context ids for multiple devices."""
|
||||
inner = (
|
||||
select_events_context_id_subquery(start_day, end_day, event_types)
|
||||
select_events_context_id_subquery(start_day, end_day, event_type_ids)
|
||||
.where(apply_event_device_id_matchers(json_quotable_device_ids))
|
||||
.subquery()
|
||||
)
|
||||
@ -47,14 +47,14 @@ def _apply_devices_context_union(
|
||||
sel: Select,
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
json_quotable_device_ids: list[str],
|
||||
) -> CompoundSelect:
|
||||
"""Generate a CTE to find the device context ids and a query to find linked row."""
|
||||
devices_cte: CTE = _select_device_id_context_ids_sub_query(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
json_quotable_device_ids,
|
||||
).cte()
|
||||
return sel.union_all(
|
||||
@ -77,18 +77,18 @@ def _apply_devices_context_union(
|
||||
def devices_stmt(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
json_quotable_device_ids: list[str],
|
||||
) -> StatementLambdaElement:
|
||||
"""Generate a logbook query for multiple devices."""
|
||||
stmt = lambda_stmt(
|
||||
lambda: _apply_devices_context_union(
|
||||
select_events_without_states(start_day, end_day, event_types).where(
|
||||
select_events_without_states(start_day, end_day, event_type_ids).where(
|
||||
apply_event_device_id_matchers(json_quotable_device_ids)
|
||||
),
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
json_quotable_device_ids,
|
||||
).order_by(Events.time_fired_ts)
|
||||
)
|
||||
|
@ -35,13 +35,13 @@ from .common import (
|
||||
def _select_entities_context_ids_sub_query(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
states_metadata_ids: Collection[int],
|
||||
json_quoted_entity_ids: list[str],
|
||||
) -> Select:
|
||||
"""Generate a subquery to find context ids for multiple entities."""
|
||||
union = union_all(
|
||||
select_events_context_id_subquery(start_day, end_day, event_types).where(
|
||||
select_events_context_id_subquery(start_day, end_day, event_type_ids).where(
|
||||
apply_event_entity_id_matchers(json_quoted_entity_ids)
|
||||
),
|
||||
apply_entities_hints(select(States.context_id_bin))
|
||||
@ -57,7 +57,7 @@ def _apply_entities_context_union(
|
||||
sel: Select,
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
states_metadata_ids: Collection[int],
|
||||
json_quoted_entity_ids: list[str],
|
||||
) -> CompoundSelect:
|
||||
@ -65,7 +65,7 @@ def _apply_entities_context_union(
|
||||
entities_cte: CTE = _select_entities_context_ids_sub_query(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
states_metadata_ids,
|
||||
json_quoted_entity_ids,
|
||||
).cte()
|
||||
@ -95,19 +95,19 @@ def _apply_entities_context_union(
|
||||
def entities_stmt(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
states_metadata_ids: Collection[int],
|
||||
json_quoted_entity_ids: list[str],
|
||||
) -> StatementLambdaElement:
|
||||
"""Generate a logbook query for multiple entities."""
|
||||
return lambda_stmt(
|
||||
lambda: _apply_entities_context_union(
|
||||
select_events_without_states(start_day, end_day, event_types).where(
|
||||
select_events_without_states(start_day, end_day, event_type_ids).where(
|
||||
apply_event_entity_id_matchers(json_quoted_entity_ids)
|
||||
),
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
states_metadata_ids,
|
||||
json_quoted_entity_ids,
|
||||
).order_by(Events.time_fired_ts)
|
||||
|
@ -35,14 +35,14 @@ from .entities import (
|
||||
def _select_entities_device_id_context_ids_sub_query(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
states_metadata_ids: Collection[int],
|
||||
json_quoted_entity_ids: list[str],
|
||||
json_quoted_device_ids: list[str],
|
||||
) -> Select:
|
||||
"""Generate a subquery to find context ids for multiple entities and multiple devices."""
|
||||
union = union_all(
|
||||
select_events_context_id_subquery(start_day, end_day, event_types).where(
|
||||
select_events_context_id_subquery(start_day, end_day, event_type_ids).where(
|
||||
_apply_event_entity_id_device_id_matchers(
|
||||
json_quoted_entity_ids, json_quoted_device_ids
|
||||
)
|
||||
@ -60,7 +60,7 @@ def _apply_entities_devices_context_union(
|
||||
sel: Select,
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
states_metadata_ids: Collection[int],
|
||||
json_quoted_entity_ids: list[str],
|
||||
json_quoted_device_ids: list[str],
|
||||
@ -68,7 +68,7 @@ def _apply_entities_devices_context_union(
|
||||
devices_entities_cte: CTE = _select_entities_device_id_context_ids_sub_query(
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
states_metadata_ids,
|
||||
json_quoted_entity_ids,
|
||||
json_quoted_device_ids,
|
||||
@ -103,7 +103,7 @@ def _apply_entities_devices_context_union(
|
||||
def entities_devices_stmt(
|
||||
start_day: float,
|
||||
end_day: float,
|
||||
event_types: tuple[str, ...],
|
||||
event_type_ids: tuple[int, ...],
|
||||
states_metadata_ids: Collection[int],
|
||||
json_quoted_entity_ids: list[str],
|
||||
json_quoted_device_ids: list[str],
|
||||
@ -111,14 +111,14 @@ def entities_devices_stmt(
|
||||
"""Generate a logbook query for multiple entities."""
|
||||
stmt = lambda_stmt(
|
||||
lambda: _apply_entities_devices_context_union(
|
||||
select_events_without_states(start_day, end_day, event_types).where(
|
||||
select_events_without_states(start_day, end_day, event_type_ids).where(
|
||||
_apply_event_entity_id_device_id_matchers(
|
||||
json_quoted_entity_ids, json_quoted_device_ids
|
||||
)
|
||||
),
|
||||
start_day,
|
||||
end_day,
|
||||
event_types,
|
||||
event_type_ids,
|
||||
states_metadata_ids,
|
||||
json_quoted_entity_ids,
|
||||
json_quoted_device_ids,
|
||||
|
@ -8,6 +8,7 @@ from .context import (
|
||||
uuid_hex_to_bytes_or_none,
|
||||
)
|
||||
from .database import DatabaseEngine, DatabaseOptimizer, UnsupportedDialect
|
||||
from .event import extract_event_type_ids
|
||||
from .state import LazyState, extract_metadata_ids, row_to_compressed_state
|
||||
from .statistics import (
|
||||
CalendarStatisticPeriod,
|
||||
@ -43,6 +44,7 @@ __all__ = [
|
||||
"bytes_to_ulid_or_none",
|
||||
"bytes_to_uuid_hex_or_none",
|
||||
"datetime_to_timestamp_or_none",
|
||||
"extract_event_type_ids",
|
||||
"extract_metadata_ids",
|
||||
"process_datetime_to_timestamp",
|
||||
"process_timestamp",
|
||||
|
13
homeassistant/components/recorder/models/event.py
Normal file
13
homeassistant/components/recorder/models/event.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""Models events in for Recorder."""
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def extract_event_type_ids(
|
||||
event_type_to_event_type_id: dict[str, int | None],
|
||||
) -> list[int]:
|
||||
"""Extract event_type ids from event_type_to_event_type_id."""
|
||||
return [
|
||||
event_type_id
|
||||
for event_type_id in event_type_to_event_type_id.values()
|
||||
if event_type_id is not None
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user