From jr-agent-skills
Optimize SQLite database performance through configuration, schema design, indexing, and query tuning. Use when users ask to improve SQLite speed, reduce latency, optimize queries, configure PRAGMAs, fix slow queries, handle concurrency, optimize writes/inserts, or tune SQLite for production. Triggers on mentions of SQLite performance, slow queries, PRAGMA settings, WAL mode, indexing strategies, bulk inserts, or database maintenance (VACUUM, ANALYZE).
How this skill is triggered — by the user, by Claude, or both
Slash command
/jr-agent-skills:sqlite-optimizationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Set these PRAGMAs on every connection for most applications:
Set these PRAGMAs on every connection for most applications:
PRAGMA journal_mode = WAL; -- Non-blocking concurrent reads/writes
PRAGMA synchronous = NORMAL; -- Fast commits, safe for WAL mode
PRAGMA foreign_keys = ON; -- Data integrity
PRAGMA cache_size = -64000; -- 64MB cache (negative = KB)
PRAGMA temp_store = MEMORY; -- In-memory temp tables/sorting
PRAGMA busy_timeout = 5000; -- 5s retry on lock contention
PRAGMA mmap_size = 2147483648; -- 2GB memory-mapped I/O (benchmark first)
Run periodically:
PRAGMA optimize; -- Update query planner statistics
EXPLAIN QUERY PLAN SELECT ...;
Key indicators:
SCAN TABLE → Full table scan (O(N)) — needs index or query rewriteSEARCH TABLE USING INDEX → Index lookup (O(log N)) — goodCOVERING INDEX → Index-only scan, no table lookup — optimalUSE TEMP B-TREE → Sorting not covered by index — consider index with ORDER BY columnsUse INTEGER PRIMARY KEY for rowid alias:
CREATE TABLE users (
id INTEGER PRIMARY KEY, -- Alias for rowid, no extra index
email TEXT NOT NULL,
created_at TEXT
);
Choose appropriate types:
INTEGER for IDs, counters, booleansREAL for floatsTEXT for stringsWITHOUT ROWID for junction tables:
CREATE TABLE user_roles (
user_id INTEGER,
role_id INTEGER,
PRIMARY KEY (user_id, role_id)
) WITHOUT ROWID; -- Clustered index, no rowid overhead
Create indexes for real query patterns:
-- For: WHERE user_id = ? AND created_at >= ? ORDER BY created_at DESC
CREATE INDEX idx_orders_user_created
ON orders (user_id, created_at DESC);
Covering indexes eliminate table lookups:
-- For: SELECT user_id, total FROM orders WHERE user_id = ?
CREATE INDEX idx_orders_cover
ON orders (user_id, created_at DESC, total);
Partial indexes for subsets:
CREATE INDEX idx_active_users
ON users (email) WHERE status = 'active';
Expression indexes:
CREATE INDEX idx_users_lower_email
ON users (lower(email));
Avoid indexing:
Always batch writes in transactions:
BEGIN TRANSACTION;
INSERT INTO logs (...) VALUES (...);
-- ... many more inserts
COMMIT;
Throughput jumps from ~50 inserts/sec (autocommit) to 50,000+ inserts/sec.
Use prepared statements:
stmt = conn.prepare("INSERT INTO logs (ts, level, msg) VALUES (?, ?, ?)")
for row in data:
stmt.execute(row)
Optimal batch size: 1,000–10,000 rows balances throughput vs memory.
WAL mode enables concurrent readers + one writer:
.wal and .shm files alongside main DBHandle contention:
PRAGMA busy_timeout = 5000; -- Retry for 5 seconds before SQLITE_BUSY
Architecture pattern: Single writer thread/process + many reader connections.
VACUUM after large deletes:
VACUUM; -- Rebuilds and defragments DB file
Auto-vacuum for incremental reclaim:
PRAGMA auto_vacuum = INCREMENTAL;
VACUUM; -- Apply change
-- Then periodically:
PRAGMA incremental_vacuum;
Keep statistics fresh:
PRAGMA optimize; -- Smart, selective ANALYZE
-- Or full:
ANALYZE;
| Problem | Solution |
|---|---|
SELECT * | List only needed columns |
| Loop with single inserts | Batch in transaction |
| Correlated subquery per row | Rewrite as JOIN |
| Index on every column | Index only queried columns |
No busy_timeout | Set appropriate timeout |
| Rollback journal mode | Switch to WAL |
| Never running ANALYZE | Run PRAGMA optimize periodically |
Mobile (iOS/Android):
synchronous = NORMALServer/Desktop:
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Implements vector databases with Pinecone, Weaviate, Qdrant, Milvus, pgvector for semantic search, RAG, recommendations, and similarity systems. Optimizes embeddings, indexing, and hybrid search.
npx claudepluginhub jrajasekera/jr-agent-skills --plugin jr-agent-skills