diff --git a/homeassistant/components/recorder/__init__.py b/homeassistant/components/recorder/__init__.py index 8ac610f1bcf..0ed5c3126b7 100644 --- a/homeassistant/components/recorder/__init__.py +++ b/homeassistant/components/recorder/__init__.py @@ -166,6 +166,7 @@ class Recorder(threading.Thread): migration.migrate_schema(self) self._setup_run() connected = True + _LOGGER.debug("Connected to recorder database") except Exception as err: # pylint: disable=broad-except _LOGGER.error("Error during connection setup: %s (retrying " "in %s seconds)", err, CONNECT_RETRY_WAIT) diff --git a/homeassistant/components/recorder/migration.py b/homeassistant/components/recorder/migration.py index 09c5e9837c3..0fac32bdec7 100644 --- a/homeassistant/components/recorder/migration.py +++ b/homeassistant/components/recorder/migration.py @@ -36,25 +36,34 @@ def migrate_schema(instance): _LOGGER.info("Upgrade to version %s done", new_version) -def _apply_update(engine, new_version): - """Perform operations to bring schema up to date.""" +def _create_index(engine, table_name, index_name): + """Create an index for the specified table. + + The index name should match the name given for the index + within the table definition described in the models + """ from sqlalchemy import Table from . import models - if new_version == 1: - def create_index(table_name, column_name): - """Create an index for the specified table and column.""" - table = Table(table_name, models.Base.metadata) - name = "_".join(("ix", table_name, column_name)) - # Look up the index object that was created from the models - index = next(idx for idx in table.indexes if idx.name == name) - _LOGGER.debug("Creating index for table %s column %s", - table_name, column_name) - index.create(engine) - _LOGGER.debug("Index creation done for table %s column %s", - table_name, column_name) + table = Table(table_name, models.Base.metadata) + _LOGGER.debug("Looking up index for table %s", table_name) + # Look up the index object by name from the table is the the models + index = next(idx for idx in table.indexes if idx.name == index_name) + _LOGGER.debug("Creating %s index", index_name) + index.create(engine) + _LOGGER.debug("Finished creating %s", index_name) - create_index("events", "time_fired") + +def _apply_update(engine, new_version): + """Perform operations to bring schema up to date.""" + if new_version == 1: + _create_index(engine, "events", "ix_events_time_fired") + elif new_version == 2: + # Create compound start/end index for recorder_runs + _create_index(engine, "recorder_runs", "ix_recorder_runs_start_end") + # Create indexes for states + _create_index(engine, "states", "ix_states_last_updated") + _create_index(engine, "states", "ix_states_entity_id_created") else: raise ValueError("No schema migration defined for version {}" .format(new_version)) diff --git a/homeassistant/components/recorder/models.py b/homeassistant/components/recorder/models.py index 4bc044a51bd..ce42ba187c2 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -16,7 +16,7 @@ from homeassistant.remote import JSONEncoder # pylint: disable=invalid-name Base = declarative_base() -SCHEMA_VERSION = 1 +SCHEMA_VERSION = 2 _LOGGER = logging.getLogger(__name__) @@ -66,13 +66,16 @@ class States(Base): # type: ignore attributes = Column(Text) event_id = Column(Integer, ForeignKey('events.event_id')) last_changed = Column(DateTime(timezone=True), default=datetime.utcnow) - last_updated = Column(DateTime(timezone=True), default=datetime.utcnow) + last_updated = Column(DateTime(timezone=True), default=datetime.utcnow, + index=True) created = Column(DateTime(timezone=True), default=datetime.utcnow) __table_args__ = (Index('states__state_changes', 'last_changed', 'last_updated', 'entity_id'), Index('states__significant_changes', - 'domain', 'last_updated', 'entity_id'), ) + 'domain', 'last_updated', 'entity_id'), + Index('ix_states_entity_id_created', + 'entity_id', 'created'),) @staticmethod def from_event(event): @@ -124,6 +127,8 @@ class RecorderRuns(Base): # type: ignore closed_incorrect = Column(Boolean, default=False) created = Column(DateTime(timezone=True), default=datetime.utcnow) + __table_args__ = (Index('ix_recorder_runs_start_end', 'start', 'end'),) + def entity_ids(self, point_in_time=None): """Return the entity ids that existed in this run.