From 8096be768d1098547dcdfff813158cd94d9acf5e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 28 Mar 2023 17:54:03 -1000 Subject: [PATCH] Isolate the sql integration with a separate query cache (#90438) * Isolate the sql integration with a seperate query cache If there were a lot of sql integrations they could affect the performance of the recorder/logbook/history since they were sharing the same LRU and since the sql sensor updates frequently it would evict the recorder queries from the LRU. * generate in stmt * avoid double gen * Revert "avoid double gen" This reverts commit 6a5aa65268da12e2cd0e73e0bfb46db6e7e6214d. --- homeassistant/components/sql/sensor.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sql/sensor.py b/homeassistant/components/sql/sensor.py index 93d3e7be355..c19c2c258bc 100644 --- a/homeassistant/components/sql/sensor.py +++ b/homeassistant/components/sql/sensor.py @@ -6,9 +6,12 @@ import decimal import logging import sqlalchemy +from sqlalchemy import lambda_stmt from sqlalchemy.engine import Result from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session, scoped_session, sessionmaker +from sqlalchemy.sql.lambdas import StatementLambdaElement +from sqlalchemy.util import LRUCache from homeassistant.components.recorder import CONF_DB_URL, get_instance from homeassistant.components.sensor import ( @@ -38,6 +41,8 @@ from .util import resolve_db_url _LOGGER = logging.getLogger(__name__) +_SQL_LAMBDA_CACHE: LRUCache = LRUCache(1000) + def redact_credentials(data: str) -> str: """Redact credentials from string data.""" @@ -202,6 +207,12 @@ def _validate_and_get_session_maker_for_db_url(db_url: str) -> scoped_session | sess.close() +def _generate_lambda_stmt(query: str) -> StatementLambdaElement: + """Generate the lambda statement.""" + text = sqlalchemy.text(query) + return lambda_stmt(lambda: text, lambda_cache=_SQL_LAMBDA_CACHE) + + class SQLSensor(SensorEntity): """Representation of an SQL sensor.""" @@ -234,6 +245,7 @@ class SQLSensor(SensorEntity): self._attr_extra_state_attributes = {} self._attr_unique_id = unique_id self._use_database_executor = use_database_executor + self._lambda_stmt = _generate_lambda_stmt(query) if not yaml and unique_id: self._attr_device_info = DeviceInfo( entry_type=DeviceEntryType.SERVICE, @@ -255,7 +267,7 @@ class SQLSensor(SensorEntity): self._attr_extra_state_attributes = {} sess: scoped_session = self.sessionmaker() try: - result: Result = sess.execute(sqlalchemy.text(self._query)) + result: Result = sess.execute(self._lambda_stmt) except SQLAlchemyError as err: _LOGGER.error( "Error executing query %s: %s",