mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Improve history api performance part 4 (#36783)
This builds on #35822 Minimize the amount of data selected from the database Testing: History API Response time for 1 day Average of 10 runs with minimal_response Before: 9.47s After: 4.43s
This commit is contained in:
parent
e443dc1274
commit
83e3f680bf
@ -51,6 +51,18 @@ NEED_ATTRIBUTE_DOMAINS = {"climate", "water_heater", "thermostat", "script"}
|
|||||||
SCRIPT_DOMAIN = "script"
|
SCRIPT_DOMAIN = "script"
|
||||||
ATTR_CAN_CANCEL = "can_cancel"
|
ATTR_CAN_CANCEL = "can_cancel"
|
||||||
|
|
||||||
|
QUERY_STATES = [
|
||||||
|
States.domain,
|
||||||
|
States.entity_id,
|
||||||
|
States.state,
|
||||||
|
States.attributes,
|
||||||
|
States.last_changed,
|
||||||
|
States.last_updated,
|
||||||
|
States.created,
|
||||||
|
States.context_id,
|
||||||
|
States.context_user_id,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_significant_states(hass, *args, **kwargs):
|
def get_significant_states(hass, *args, **kwargs):
|
||||||
"""Wrap _get_significant_states with a sql session."""
|
"""Wrap _get_significant_states with a sql session."""
|
||||||
@ -79,7 +91,7 @@ def _get_significant_states(
|
|||||||
timer_start = time.perf_counter()
|
timer_start = time.perf_counter()
|
||||||
|
|
||||||
if significant_changes_only:
|
if significant_changes_only:
|
||||||
query = session.query(States).filter(
|
query = session.query(*QUERY_STATES).filter(
|
||||||
(
|
(
|
||||||
States.domain.in_(SIGNIFICANT_DOMAINS)
|
States.domain.in_(SIGNIFICANT_DOMAINS)
|
||||||
| (States.last_changed == States.last_updated)
|
| (States.last_changed == States.last_updated)
|
||||||
@ -87,7 +99,7 @@ def _get_significant_states(
|
|||||||
& (States.last_updated > start_time)
|
& (States.last_updated > start_time)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
query = session.query(States).filter(States.last_updated > start_time)
|
query = session.query(*QUERY_STATES).filter(States.last_updated > start_time)
|
||||||
|
|
||||||
if filters:
|
if filters:
|
||||||
query = filters.apply(query, entity_ids)
|
query = filters.apply(query, entity_ids)
|
||||||
@ -119,7 +131,7 @@ def state_changes_during_period(hass, start_time, end_time=None, entity_id=None)
|
|||||||
"""Return states changes during UTC period start_time - end_time."""
|
"""Return states changes during UTC period start_time - end_time."""
|
||||||
|
|
||||||
with session_scope(hass=hass) as session:
|
with session_scope(hass=hass) as session:
|
||||||
query = session.query(States).filter(
|
query = session.query(*QUERY_STATES).filter(
|
||||||
(States.last_changed == States.last_updated)
|
(States.last_changed == States.last_updated)
|
||||||
& (States.last_updated > start_time)
|
& (States.last_updated > start_time)
|
||||||
)
|
)
|
||||||
@ -145,7 +157,9 @@ def get_last_state_changes(hass, number_of_states, entity_id):
|
|||||||
start_time = dt_util.utcnow()
|
start_time = dt_util.utcnow()
|
||||||
|
|
||||||
with session_scope(hass=hass) as session:
|
with session_scope(hass=hass) as session:
|
||||||
query = session.query(States).filter(States.last_changed == States.last_updated)
|
query = session.query(*QUERY_STATES).filter(
|
||||||
|
States.last_changed == States.last_updated
|
||||||
|
)
|
||||||
|
|
||||||
if entity_id is not None:
|
if entity_id is not None:
|
||||||
query = query.filter_by(entity_id=entity_id.lower())
|
query = query.filter_by(entity_id=entity_id.lower())
|
||||||
@ -196,7 +210,7 @@ def _get_states_with_session(
|
|||||||
if run is None:
|
if run is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
query = session.query(States)
|
query = session.query(*QUERY_STATES)
|
||||||
|
|
||||||
if entity_ids and len(entity_ids) == 1:
|
if entity_ids and len(entity_ids) == 1:
|
||||||
# Use an entirely different (and extremely fast) query if we only
|
# Use an entirely different (and extremely fast) query if we only
|
||||||
@ -257,7 +271,7 @@ def _get_states_with_session(
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
state
|
state
|
||||||
for state in execute(query)
|
for state in (States.to_native(row) for row in execute(query, to_native=False))
|
||||||
if not state.attributes.get(ATTR_HIDDEN, False)
|
if not state.attributes.get(ATTR_HIDDEN, False)
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -316,7 +330,9 @@ def _sorted_states_to_json(
|
|||||||
ent_results.extend(
|
ent_results.extend(
|
||||||
[
|
[
|
||||||
native_state
|
native_state
|
||||||
for native_state in (db_state.to_native() for db_state in group)
|
for native_state in (
|
||||||
|
States.to_native(db_state) for db_state in group
|
||||||
|
)
|
||||||
if (
|
if (
|
||||||
domain != SCRIPT_DOMAIN
|
domain != SCRIPT_DOMAIN
|
||||||
or native_state.attributes.get(ATTR_CAN_CANCEL)
|
or native_state.attributes.get(ATTR_CAN_CANCEL)
|
||||||
@ -331,16 +347,16 @@ def _sorted_states_to_json(
|
|||||||
# in-between only provide the "state" and the
|
# in-between only provide the "state" and the
|
||||||
# "last_changed".
|
# "last_changed".
|
||||||
if not ent_results:
|
if not ent_results:
|
||||||
ent_results.append(next(group).to_native())
|
ent_results.append(States.to_native(next(group)))
|
||||||
|
|
||||||
initial_state = ent_results[-1]
|
initial_state = ent_results[-1]
|
||||||
prev_state = ent_results[-1]
|
prev_state = ent_results[-1]
|
||||||
initial_state_count = len(ent_results)
|
initial_state_count = len(ent_results)
|
||||||
|
|
||||||
for db_state in group:
|
for db_state in group:
|
||||||
if ATTR_HIDDEN in db_state.attributes and db_state.to_native().attributes.get(
|
if ATTR_HIDDEN in db_state.attributes and States.to_native(
|
||||||
ATTR_HIDDEN, False
|
db_state
|
||||||
):
|
).attributes.get(ATTR_HIDDEN, False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# With minimal response we do not care about attribute
|
# With minimal response we do not care about attribute
|
||||||
@ -366,7 +382,7 @@ def _sorted_states_to_json(
|
|||||||
# There was at least one state change
|
# There was at least one state change
|
||||||
# replace the last minimal state with
|
# replace the last minimal state with
|
||||||
# a full state
|
# a full state
|
||||||
ent_results[-1] = prev_state.to_native()
|
ent_results[-1] = States.to_native(prev_state)
|
||||||
|
|
||||||
# Filter out the empty lists if some states had 0 results.
|
# Filter out the empty lists if some states had 0 results.
|
||||||
return {key: val for key, val in result.items() if val}
|
return {key: val for key, val in result.items() if val}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user