From 48b142689151447c7ad42743eb9d80499ab1b2cc Mon Sep 17 00:00:00 2001 From: Greg <{ID}+{username}@users.noreply.github.com> Date: Fri, 8 May 2026 15:59:23 -0700 Subject: [PATCH] Add additional indicies on event and review tables. Every events or timeline endpoint filters on event start time and camera, this should speed things up by avoiding a range scan on the table. --- frigate/api/event.py | 20 +++++++++++++++- migrations/036_add_perf_indexes.py | 37 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 migrations/036_add_perf_indexes.py diff --git a/frigate/api/event.py b/frigate/api/event.py index fc7c58c375..ea99cab561 100644 --- a/frigate/api/event.py +++ b/frigate/api/event.py @@ -399,13 +399,31 @@ def events_explore( label_counts = {} + explore_columns = ( + Event.id, + Event.camera, + Event.label, + Event.sub_label, + Event.zones, + Event.start_time, + Event.end_time, + Event.has_clip, + Event.has_snapshot, + Event.plus_id, + Event.retain_indefinitely, + Event.top_score, + Event.false_positive, + Event.box, + Event.data, + ) + def event_generator(): for label_obj in distinct_labels.iterator(): label = label_obj.label # get most recent events for this label label_events = ( - Event.select() + Event.select(*explore_columns) .where((Event.label == label) & (Event.camera << allowed_cameras)) .order_by(Event.start_time.desc()) .limit(limit) diff --git a/migrations/036_add_perf_indexes.py b/migrations/036_add_perf_indexes.py new file mode 100644 index 0000000000..3796aa6acf --- /dev/null +++ b/migrations/036_add_perf_indexes.py @@ -0,0 +1,37 @@ +"""Peewee migrations -- 036_add_perf_indexes.py. + +Adds composite/single-column indexes to speed up the most common queries +issued by the web UI on initial page load: + +- event(camera, start_time DESC): /events list filtered by camera + time range +- reviewsegment(camera, start_time DESC): /api/review filtered by camera + time range +- reviewsegment(end_time): supports the end_time > after half of /api/review's range + +The existing event(label, start_time DESC) index from migration 027 already +covers /events/explore, so it is intentionally not duplicated here. +""" + +import peewee as pw + +SQL = pw.SQL + + +def migrate(migrator, database, fake=False, **kwargs): + migrator.sql( + 'CREATE INDEX IF NOT EXISTS "event_camera_start_time" ' + 'ON "event" ("camera", "start_time" DESC)' + ) + migrator.sql( + 'CREATE INDEX IF NOT EXISTS "reviewsegment_camera_start_time" ' + 'ON "reviewsegment" ("camera", "start_time" DESC)' + ) + migrator.sql( + 'CREATE INDEX IF NOT EXISTS "reviewsegment_end_time" ' + 'ON "reviewsegment" ("end_time")' + ) + + +def rollback(migrator, database, fake=False, **kwargs): + migrator.sql('DROP INDEX IF EXISTS "event_camera_start_time"') + migrator.sql('DROP INDEX IF EXISTS "reviewsegment_camera_start_time"') + migrator.sql('DROP INDEX IF EXISTS "reviewsegment_end_time"')