fix(#142): index device_status_log + de-dupe its CREATE TABLE

The dashboard uptime query (WHERE device_id=? AND timestamp>?) and the
per-device retention prune (WHERE device_id=? AND timestamp<?) were both full
table scans. At 1M+ rows (the outage report) this was the dashboard-degradation
cause that persisted even after the reconnect storm stopped.

- schema.sql: add idx_device_status_log_device_ts(device_id, timestamp); both
  queries now SEARCH ... USING INDEX instead of SCAN (verified via EXPLAIN).
- database.js: same index as a migration for existing DBs (idempotent).
- schema.sql defined device_status_log twice; drop the duplicate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ScreenTinker 2026-06-27 18:54:57 -05:00
parent f96b65576f
commit d90cfb3986
2 changed files with 10 additions and 7 deletions

View file

@ -225,6 +225,11 @@ const migrations = [
"ALTER TABLE devices ADD COLUMN ota_target_version TEXT", "ALTER TABLE devices ADD COLUMN ota_target_version TEXT",
"ALTER TABLE devices ADD COLUMN ota_attempts INTEGER DEFAULT 0", "ALTER TABLE devices ADD COLUMN ota_attempts INTEGER DEFAULT 0",
"ALTER TABLE devices ADD COLUMN ota_updated_at INTEGER", "ALTER TABLE devices ADD COLUMN ota_updated_at INTEGER",
// #142: index device_status_log for the per-device + time-window access pattern.
// schema.sql creates this on fresh installs; this migration covers existing DBs.
// Both the dashboard uptime query and the retention prune were full scans — the
// dashboard-degradation cause once the table reached 1M+ rows.
"CREATE INDEX IF NOT EXISTS idx_device_status_log_device_ts ON device_status_log(device_id, timestamp)",
]; ];
// Apply each ALTER idempotently. A "duplicate column name" / "already exists" // Apply each ALTER idempotently. A "duplicate column name" / "already exists"
// error means the column is already present (expected on a migrated DB) - benign. // error means the column is already present (expected on a migrated DB) - benign.

View file

@ -463,6 +463,11 @@ CREATE TABLE IF NOT EXISTS device_status_log (
status TEXT NOT NULL, status TEXT NOT NULL,
timestamp INTEGER NOT NULL DEFAULT (strftime('%s','now')) timestamp INTEGER NOT NULL DEFAULT (strftime('%s','now'))
); );
-- #142: index the per-device + time-window access pattern. Both the dashboard
-- uptime query (WHERE device_id=? AND timestamp>?) and the retention prune
-- (WHERE device_id=? AND timestamp<?) were full table scans; at 1M+ rows that
-- was the dashboard-degradation cause in the outage report.
CREATE INDEX IF NOT EXISTS idx_device_status_log_device_ts ON device_status_log(device_id, timestamp);
-- ===================== DEVICE FINGERPRINTS ===================== -- ===================== DEVICE FINGERPRINTS =====================
@ -484,13 +489,6 @@ CREATE TABLE IF NOT EXISTS alert_configs (
created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')) created_at INTEGER NOT NULL DEFAULT (strftime('%s','now'))
); );
CREATE TABLE IF NOT EXISTS device_status_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL,
status TEXT NOT NULL,
timestamp INTEGER NOT NULL DEFAULT (strftime('%s','now'))
);
-- ===================== PLAYER DEBUG LOGS ===================== -- ===================== PLAYER DEBUG LOGS =====================
-- Smart TVs (Tizen, WebOS, Fire TV, etc.) have no accessible devtools. The -- Smart TVs (Tizen, WebOS, Fire TV, etc.) have no accessible devtools. The
-- player captures errors into window.__debugLog client-side and POSTs them -- player captures errors into window.__debugLog client-side and POSTs them