restore lost performance

This commit is contained in:
J. Nick Koston
2023-04-10 11:59:08 -10:00
parent 79078670dd
commit 934795dafd

View File

@@ -140,6 +140,7 @@ def get_significant_states(
def _significant_states_stmt( def _significant_states_stmt(
start_time_ts: float, start_time_ts: float,
end_time_ts: float | None, end_time_ts: float | None,
single_metadata_id: int | None,
metadata_ids: list[int], metadata_ids: list[int],
metadata_ids_in_significant_domains: list[int], metadata_ids_in_significant_domains: list[int],
significant_changes_only: bool, significant_changes_only: bool,
@@ -176,7 +177,11 @@ def _significant_states_stmt(
union_all( union_all(
_select_from_subquery( _select_from_subquery(
_get_start_time_state_stmt( _get_start_time_state_stmt(
run_start_ts, start_time_ts, metadata_ids, no_attributes run_start_ts,
start_time_ts,
single_metadata_id,
metadata_ids,
no_attributes,
).subquery(), ).subquery(),
no_attributes, no_attributes,
), ),
@@ -242,10 +247,14 @@ def get_significant_states_with_session(
include_start_time_state = False include_start_time_state = False
start_time_ts = dt_util.utc_to_timestamp(start_time) start_time_ts = dt_util.utc_to_timestamp(start_time)
end_time_ts = datetime_to_timestamp_or_none(end_time) end_time_ts = datetime_to_timestamp_or_none(end_time)
single_metadata_id: int | None = None
if len(metadata_ids) == 1:
single_metadata_id = metadata_ids[0]
stmt = lambda_stmt( stmt = lambda_stmt(
lambda: _significant_states_stmt( lambda: _significant_states_stmt(
start_time_ts, start_time_ts,
end_time_ts, end_time_ts,
single_metadata_id,
metadata_ids, metadata_ids,
metadata_ids_in_significant_domains, metadata_ids_in_significant_domains,
significant_changes_only, significant_changes_only,
@@ -254,6 +263,7 @@ def get_significant_states_with_session(
run_start_ts, run_start_ts,
), ),
track_on=[ track_on=[
bool(single_metadata_id),
bool(end_time_ts), bool(end_time_ts),
bool(significant_changes_only), bool(significant_changes_only),
bool(no_attributes), bool(no_attributes),
@@ -306,8 +316,7 @@ def get_full_significant_states_with_session(
def _state_changed_during_period_stmt( def _state_changed_during_period_stmt(
start_time_ts: float, start_time_ts: float,
end_time_ts: float | None, end_time_ts: float | None,
metadata_id: int, single_metadata_id: int,
metadata_ids: list[int],
no_attributes: bool, no_attributes: bool,
descending: bool, descending: bool,
limit: int | None, limit: int | None,
@@ -323,7 +332,7 @@ def _state_changed_during_period_stmt(
) )
& (States.last_updated_ts > start_time_ts) & (States.last_updated_ts > start_time_ts)
) )
.filter(States.metadata_id == metadata_id) .filter(States.metadata_id == single_metadata_id)
) )
if end_time_ts: if end_time_ts:
stmt = stmt.filter(States.last_updated_ts < end_time_ts) stmt = stmt.filter(States.last_updated_ts < end_time_ts)
@@ -342,8 +351,8 @@ def _state_changed_during_period_stmt(
return _select_from_subquery( return _select_from_subquery(
union_all( union_all(
_select_from_subquery( _select_from_subquery(
_get_start_time_state_stmt( _get_single_entity_start_time_stmt(
run_start_ts, start_time_ts, metadata_ids, no_attributes start_time_ts, single_metadata_id, no_attributes
).subquery(), ).subquery(),
no_attributes, no_attributes,
), ),
@@ -376,8 +385,10 @@ def state_changes_during_period(
) )
): ):
return {} return {}
metadata_id = possible_metadata_id single_metadata_id = possible_metadata_id
entity_id_to_metadata_id: dict[str, int | None] = {entity_id: metadata_id} entity_id_to_metadata_id: dict[str, int | None] = {
entity_id: single_metadata_id
}
run_start_ts: float | None = None run_start_ts: float | None = None
if include_start_time_state: if include_start_time_state:
run = recorder.get_instance(hass).recorder_runs_manager.get(start_time) run = recorder.get_instance(hass).recorder_runs_manager.get(start_time)
@@ -389,13 +400,11 @@ def state_changes_during_period(
include_start_time_state = False include_start_time_state = False
start_time_ts = dt_util.utc_to_timestamp(start_time) start_time_ts = dt_util.utc_to_timestamp(start_time)
end_time_ts = datetime_to_timestamp_or_none(end_time) end_time_ts = datetime_to_timestamp_or_none(end_time)
metadata_ids = [metadata_id]
stmt = lambda_stmt( stmt = lambda_stmt(
lambda: _state_changed_during_period_stmt( lambda: _state_changed_during_period_stmt(
start_time_ts, start_time_ts,
end_time_ts, end_time_ts,
metadata_id, single_metadata_id,
metadata_ids,
no_attributes, no_attributes,
descending, descending,
limit, limit,
@@ -555,11 +564,19 @@ def _get_run_start_ts_from_run_for_utc_point_in_time(
def _get_start_time_state_stmt( def _get_start_time_state_stmt(
run_start_ts: float, run_start_ts: float,
epoch_time: float, epoch_time: float,
single_metadata_id: int | None,
metadata_ids: list[int], metadata_ids: list[int],
no_attributes: bool, no_attributes: bool,
) -> Select: ) -> Select:
"""Return the states at a specific point in time.""" """Return the states at a specific point in time."""
if single_metadata_id:
# Use an entirely different (and extremely fast) query if we only
# have a single entity id
return _get_single_entity_start_time_stmt(
epoch_time,
single_metadata_id,
no_attributes,
)
# We have more than one entity to look at so we need to do a query on states # We have more than one entity to look at so we need to do a query on states
# since the last recorder run started. # since the last recorder run started.
return _get_states_for_entities_stmt( return _get_states_for_entities_stmt(
@@ -567,6 +584,29 @@ def _get_start_time_state_stmt(
) )
def _get_single_entity_start_time_stmt(
epoch_time: float,
metadata_id: int,
no_attributes: bool,
) -> Select:
# Use an entirely different (and extremely fast) query if we only
# have a single entity id
stmt = (
_stmt_and_join_attributes(no_attributes, True)
.filter(
States.last_updated_ts < epoch_time,
States.metadata_id == metadata_id,
)
.order_by(States.last_updated_ts.desc())
.limit(1)
)
if no_attributes:
return stmt
return stmt.outerjoin(
StateAttributes, States.attributes_id == StateAttributes.attributes_id
)
def _sorted_states_to_dict( def _sorted_states_to_dict(
states: Iterable[Row], states: Iterable[Row],
entity_ids: list[str], entity_ids: list[str],