Skip to content

Commit 3058f46

Browse files
authored
perf(sqlite): add secondary indexes for frontend queries (#77)
1 parent de1c31d commit 3058f46

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

src/sqlite.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,40 @@ def export_sqlite_to_bin(cur, conn):
2626
return (zipped_buffer)
2727

2828

29+
def create_indexes(cur):
30+
"""Add secondary indexes used by the frontend's read queries.
31+
32+
Built once after bulk inserts (rather than declared in CREATE TABLE)
33+
so each insert only writes the row, and the index is constructed in
34+
one shot at the end. This keeps worker write time down on heavy
35+
packages.
36+
37+
The picks below were chosen against the queries actually run by the
38+
frontend (see hooks/data/use-*.ts in dumpus-app):
39+
40+
- activity: every read filters on event_name + a date range, often
41+
narrowed by guild or channel. The existing PK starts with
42+
(event_name, day, hour, ...) which already covers global time-range
43+
queries, but guild/channel-scoped queries had to scan all rows in
44+
the (event_name, day) range. Two compound indexes fix that.
45+
- sessions: no PK at all, every query filters on started_date.
46+
- voice_sessions: PK leads with channel_id, but every query filters
47+
only on started_date — index it directly.
48+
- dm_channels_data and guild_channels_data: PK is on channel_id, but
49+
reads also group/filter by dm_user_id / guild_id respectively.
50+
"""
51+
statements = [
52+
'CREATE INDEX idx_activity_event_guild_day ON activity (event_name, associated_guild_id, day)',
53+
'CREATE INDEX idx_activity_event_channel_day ON activity (event_name, associated_channel_id, day)',
54+
'CREATE INDEX idx_sessions_started_date ON sessions (started_date)',
55+
'CREATE INDEX idx_voice_sessions_started_date ON voice_sessions (started_date)',
56+
'CREATE INDEX idx_dm_channels_dm_user_id ON dm_channels_data (dm_user_id)',
57+
'CREATE INDEX idx_guild_channels_guild_id ON guild_channels_data (guild_id)',
58+
]
59+
for stmt in statements:
60+
cur.execute(stmt)
61+
62+
2963
def create_new_empty_database():
3064
conn = sqlite3.connect(':memory:')
3165
cur = conn.cursor()

src/tasks.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import gzip
2424
import tempfile
2525

26-
from sqlite import create_new_empty_database, export_sqlite_to_bin
26+
from sqlite import create_new_empty_database, create_indexes, export_sqlite_to_bin
2727

2828
import os
2929
from collections import defaultdict
@@ -902,6 +902,11 @@ def _is_in_existing_event(t):
902902

903903
conn.commit()
904904

905+
# Build secondary indexes after bulk inserts but before VACUUM, so the
906+
# vacuum repacks the index pages too.
907+
create_indexes(cur)
908+
conn.commit()
909+
905910
# make database smaller
906911
cur.execute('VACUUM;')
907912

0 commit comments

Comments
 (0)