Use multiple indexed group-by queries to get start time states for MySQL (#138786)

* tweaks

* mysql

* mysql

* Update homeassistant/components/recorder/history/modern.py

* Update homeassistant/components/recorder/history/modern.py

* Update homeassistant/components/recorder/const.py

* Update homeassistant/components/recorder/statistics.py

* Apply suggestions from code review

* mysql

* mysql

* cover

* make sure db is fully init on old schema

* fixes

* fixes

* coverage

* coverage

* coverage

* s/slow_dependant_subquery/slow_dependent_subquery/g

* reword

* comment that callers are responsible for staying under the limit

* comment that callers are responsible for staying under the limit

* switch to kwargs

* reduce branching complexity

* split stats query

* preen

* split tests

* split tests
This commit is contained in:
J. Nick Koston
2025-03-02 08:13:06 -06:00
committed by GitHub
parent 0c803520a3
commit c9abe76023
15 changed files with 965 additions and 54 deletions

View File

@ -464,6 +464,7 @@ def setup_connection_for_dialect(
"""Execute statements needed for dialect connection."""
version: AwesomeVersion | None = None
slow_range_in_select = False
slow_dependent_subquery = False
if dialect_name == SupportedDialect.SQLITE:
if first_connection:
old_isolation = dbapi_connection.isolation_level # type: ignore[attr-defined]
@ -505,9 +506,8 @@ def setup_connection_for_dialect(
result = query_on_connection(dbapi_connection, "SELECT VERSION()")
version_string = result[0][0]
version = _extract_version_from_server_response(version_string)
is_maria_db = "mariadb" in version_string.lower()
if is_maria_db:
if "mariadb" in version_string.lower():
if not version or version < MIN_VERSION_MARIA_DB:
_raise_if_version_unsupported(
version or version_string, "MariaDB", MIN_VERSION_MARIA_DB
@ -523,19 +523,21 @@ def setup_connection_for_dialect(
instance.hass,
version,
)
slow_range_in_select = bool(
not version
or version < MARIADB_WITH_FIXED_IN_QUERIES_105
or MARIA_DB_106 <= version < MARIADB_WITH_FIXED_IN_QUERIES_106
or MARIA_DB_107 <= version < MARIADB_WITH_FIXED_IN_QUERIES_107
or MARIA_DB_108 <= version < MARIADB_WITH_FIXED_IN_QUERIES_108
)
elif not version or version < MIN_VERSION_MYSQL:
_raise_if_version_unsupported(
version or version_string, "MySQL", MIN_VERSION_MYSQL
)
slow_range_in_select = bool(
not version
or version < MARIADB_WITH_FIXED_IN_QUERIES_105
or MARIA_DB_106 <= version < MARIADB_WITH_FIXED_IN_QUERIES_106
or MARIA_DB_107 <= version < MARIADB_WITH_FIXED_IN_QUERIES_107
or MARIA_DB_108 <= version < MARIADB_WITH_FIXED_IN_QUERIES_108
)
else:
# MySQL
# https://github.com/home-assistant/core/issues/137178
slow_dependent_subquery = True
# Ensure all times are using UTC to avoid issues with daylight savings
execute_on_connection(dbapi_connection, "SET time_zone = '+00:00'")
@ -565,7 +567,10 @@ def setup_connection_for_dialect(
return DatabaseEngine(
dialect=SupportedDialect(dialect_name),
version=version,
optimizer=DatabaseOptimizer(slow_range_in_select=slow_range_in_select),
optimizer=DatabaseOptimizer(
slow_range_in_select=slow_range_in_select,
slow_dependent_subquery=slow_dependent_subquery,
),
max_bind_vars=DEFAULT_MAX_BIND_VARS,
)