sqlite-optimization
SQLite performance optimization techniques
What this skill does
# SQLite Optimization Skill Techniques for optimizing SQLite performance. ## PRAGMA Settings ### Performance PRAGMAs ```sql -- Enable Write-Ahead Logging (recommended for most use cases) PRAGMA journal_mode = WAL; -- Synchronous mode (tradeoff: safety vs speed) PRAGMA synchronous = NORMAL; -- Good balance -- PRAGMA synchronous = OFF; -- Fastest, but risky -- PRAGMA synchronous = FULL; -- Safest, slowest -- Memory cache size (in KB, negative = KB) PRAGMA cache_size = -64000; -- 64MB -- Memory-mapped I/O (bytes) PRAGMA mmap_size = 268435456; -- 256MB -- Busy timeout PRAGMA busy_timeout = 5000; -- 5 seconds -- Temp storage PRAGMA temp_store = MEMORY; ``` ### Query Analysis PRAGMAs ```sql -- Check foreign keys PRAGMA foreign_key_check; -- Integrity check PRAGMA integrity_check; -- Quick check PRAGMA quick_check; -- Show table info PRAGMA table_info(users); -- Show index list PRAGMA index_list(users); ``` ## Query Optimization ### EXPLAIN QUERY PLAN ```sql -- Analyze query execution plan EXPLAIN QUERY PLAN SELECT * FROM users WHERE email = '[email protected]'; -- Look for: -- "SCAN" = full table scan (often bad) -- "SEARCH" = using index (good) -- "USING INDEX" = covering index (best) ``` ### Index Optimization ```sql -- Covering index (includes all needed columns) CREATE INDEX idx_users_covering ON users(email, name, created_at); -- Now this query uses index only, no table access: SELECT email, name FROM users WHERE email LIKE 'test%'; -- Partial index for common queries CREATE INDEX idx_active_users ON users(email) WHERE active = 1; -- Expression index CREATE INDEX idx_users_lower_email ON users(lower(email)); ``` ### Query Patterns ```sql -- BAD: OR conditions prevent index use SELECT * FROM users WHERE email = '[email protected]' OR email = '[email protected]'; -- GOOD: Use UNION or IN SELECT * FROM users WHERE email IN ('[email protected]', '[email protected]'); -- BAD: Function on indexed column SELECT * FROM users WHERE lower(email) = '[email protected]'; -- GOOD: Create expression index or normalize data SELECT * FROM users WHERE email = '[email protected]'; -- BAD: LIKE with leading wildcard SELECT * FROM users WHERE name LIKE '%smith'; -- GOOD: LIKE without leading wildcard uses index SELECT * FROM users WHERE name LIKE 'smith%'; -- Use LIMIT for pagination SELECT * FROM users ORDER BY id LIMIT 20 OFFSET 0; -- Better pagination with keyset SELECT * FROM users WHERE id > ? ORDER BY id LIMIT 20; ``` ## Bulk Operations ### Batch Inserts ```typescript // Transaction for bulk inserts (much faster) const insertMany = db.transaction((items) => { const stmt = db.prepare('INSERT INTO items (name, value) VALUES (?, ?)') for (const item of items) { stmt.run(item.name, item.value) } }) // 10x-100x faster than individual inserts insertMany(largeArray) ``` ### Bulk Updates ```sql -- Update with CASE UPDATE products SET price = CASE id WHEN 1 THEN 9.99 WHEN 2 THEN 19.99 WHEN 3 THEN 29.99 END WHERE id IN (1, 2, 3); -- Update from temp table CREATE TEMP TABLE updates (id INTEGER, new_price REAL); INSERT INTO updates VALUES (1, 9.99), (2, 19.99); UPDATE products SET price = (SELECT new_price FROM updates WHERE updates.id = products.id) WHERE id IN (SELECT id FROM updates); DROP TABLE updates; ``` ## Memory Management ### Connection Pooling Pattern ```typescript class SQLitePool { private db: Database.Database constructor(filename: string) { this.db = new Database(filename) this.db.pragma('journal_mode = WAL') this.db.pragma('cache_size = -64000') } query<T>(sql: string, params?: any[]): T[] { const stmt = this.db.prepare(sql) return params ? stmt.all(...params) : stmt.all() } run(sql: string, params?: any[]): Database.RunResult { const stmt = this.db.prepare(sql) return params ? stmt.run(...params) : stmt.run() } transaction<T>(fn: () => T): T { return this.db.transaction(fn)() } close(): void { this.db.close() } } ``` ### Statement Caching ```typescript class StatementCache { private cache = new Map<string, Database.Statement>() private db: Database.Database constructor(db: Database.Database) { this.db = db } prepare(sql: string): Database.Statement { let stmt = this.cache.get(sql) if (!stmt) { stmt = this.db.prepare(sql) this.cache.set(sql, stmt) } return stmt } clear(): void { this.cache.clear() } } ``` ## Concurrency ### Read-Write Separation ```typescript // WAL mode allows concurrent reads const readDb = new Database('app.db', { readonly: true }) const writeDb = new Database('app.db') writeDb.pragma('journal_mode = WAL') // Reads don't block writes, writes don't block reads const users = readDb.prepare('SELECT * FROM users').all() writeDb.prepare('INSERT INTO users (email) VALUES (?)').run('[email protected]') ``` ### Busy Handling ```typescript // Automatic retry on busy const db = new Database('app.db') db.pragma('busy_timeout = 5000') // Wait up to 5 seconds // Or custom busy handler db.function('busy_handler', (count) => { if (count < 10) { // Wait and retry return 1 } // Give up return 0 }) ``` ## Vacuum and Maintenance ### Regular Maintenance ```sql -- Rebuild database, reclaim space VACUUM; -- Analyze for query planner ANALYZE; -- Reindex REINDEX; -- Check integrity PRAGMA integrity_check; ``` ### Auto-Vacuum ```sql -- Enable auto-vacuum (must be done before creating tables) PRAGMA auto_vacuum = FULL; -- Incremental auto-vacuum PRAGMA auto_vacuum = INCREMENTAL; PRAGMA incremental_vacuum(100); -- Free 100 pages ``` ## Benchmarking ### Simple Benchmark ```typescript function benchmark(name: string, fn: () => void, iterations = 1000): void { const start = performance.now() for (let i = 0; i < iterations; i++) { fn() } const elapsed = performance.now() - start console.log(`${name}: ${elapsed.toFixed(2)}ms (${(elapsed/iterations).toFixed(3)}ms/op)`) } // Compare approaches benchmark('Without transaction', () => { db.prepare('INSERT INTO test (value) VALUES (?)').run(1) }) const insertTx = db.transaction((n) => { const stmt = db.prepare('INSERT INTO test (value) VALUES (?)') for (let i = 0; i < n; i++) { stmt.run(i) } }) benchmark('With transaction', () => { insertTx(100) }, 10) ``` ## Integration Used by: - `backend-developer` agent - `fullstack-developer` agent
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.