From 676e2cea306720d50ce2bbc581bd82c38b186993 Mon Sep 17 00:00:00 2001 From: agessaman Date: Tue, 7 Jul 2026 22:47:47 -0700 Subject: [PATCH] perf: add covering index for airtime chart queries The airtime/utilization chart queries (get_airtime_data and get_airtime_buckets) range-scan and order packets by timestamp, selecting only timestamp/length/payload_length/transmitted. On a large packets table this forced a full scan of the row heap, saturating slow storage (e.g. a Pi SD card): each dashboard poll took longer than the client timeout, aborted polls stacked, and sustained I/O starved the transmit queue. Add a covering index on packets(timestamp, length, payload_length, transmitted) so these queries run index-only, dropping the read from the full row heap to just the index range. Verified via EXPLAIN QUERY PLAN (COVERING INDEX idx_packets_airtime). Additive and idempotent. --- repeater/data_acquisition/sqlite_handler.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/repeater/data_acquisition/sqlite_handler.py b/repeater/data_acquisition/sqlite_handler.py index 025c1bc..9a7183c 100644 --- a/repeater/data_acquisition/sqlite_handler.py +++ b/repeater/data_acquisition/sqlite_handler.py @@ -191,6 +191,14 @@ class SQLiteHandler: conn.execute( "CREATE INDEX IF NOT EXISTS idx_packets_transmitted ON packets(transmitted)" ) + # Covering index for the airtime/utilization charts. get_airtime_data + # and get_airtime_buckets range-scan and order by timestamp, selecting + # only these columns; keeping them all in the index lets SQLite serve + # the query index-only, avoiding a full scan of the (large) row heap. + conn.execute( + "CREATE INDEX IF NOT EXISTS idx_packets_airtime " + "ON packets(timestamp, length, payload_length, transmitted)" + ) conn.execute( "CREATE INDEX IF NOT EXISTS idx_adverts_timestamp ON adverts(timestamp)" )