From 9b2bd14db6e9ffe592fa0eeef94497041dfd06d8 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:28:53 -0500 Subject: [PATCH] optimize recordings/summary endpoint db query replace strftime with integer arithmetic. increases speed by about 6x, especially noticeable for installs with long retention days --- frigate/api/record.py | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/frigate/api/record.py b/frigate/api/record.py index 6eeb9fbe6..979430325 100644 --- a/frigate/api/record.py +++ b/frigate/api/record.py @@ -1,5 +1,6 @@ """Recording APIs.""" +import datetime as dt import logging from datetime import datetime, timedelta from functools import reduce @@ -97,45 +98,24 @@ def all_recordings_summary( days: dict[str, bool] = {} for period_start, period_end, period_offset in dst_periods: - hours_offset = int(period_offset / 60 / 60) - minutes_offset = int(period_offset / 60 - hours_offset * 60) - period_hour_modifier = f"{hours_offset} hour" - period_minute_modifier = f"{minutes_offset} minute" + # Use integer division instead of strftime(datetime(...)) — orders of + # magnitude cheaper per row and avoids a temp B-tree for GROUP BY. + day_expr = ((Recordings.start_time + period_offset) / 86400).cast("int") period_query = ( - Recordings.select( - fn.strftime( - "%Y-%m-%d", - fn.datetime( - Recordings.start_time, - "unixepoch", - period_hour_modifier, - period_minute_modifier, - ), - ).alias("day") - ) + Recordings.select(day_expr.alias("day_idx")) .where( (Recordings.camera << camera_list) & (Recordings.end_time >= period_start) & (Recordings.start_time <= period_end) ) - .group_by( - fn.strftime( - "%Y-%m-%d", - fn.datetime( - Recordings.start_time, - "unixepoch", - period_hour_modifier, - period_minute_modifier, - ), - ) - ) - .order_by(Recordings.start_time.desc()) + .distinct() .namedtuples() ) for g in period_query: - days[g.day] = True + day_str = (dt.date(1970, 1, 1) + dt.timedelta(days=g.day_idx)).isoformat() + days[day_str] = True return JSONResponse(content=dict(sorted(days.items())))