perf(db): drop redundant idx_edges_source / idx_edges_target (#142)
Both narrow indexes are fully covered by the existing (source, kind) and (target, kind) composites via SQLite's left-prefix scan, so they're dead weight on every write. Empirical measurements (from the spike script in PR #122 on a 50K-node / 250K-edge synthetic DB): - DB size: 34.7 MB → 27.0 MB (-22.2%) - Bulk insert (250K edges): 590ms → 431ms (1.37× faster) - source/target lookup latency: no regression Adds migration v4 to drop both on existing databases; fresh-DB schema no longer creates them. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
153fd1e974
commit
a460b856c2
@@ -305,7 +305,7 @@ describe('Database Connection', () => {
|
|||||||
|
|
||||||
const version = db.getSchemaVersion();
|
const version = db.getSchemaVersion();
|
||||||
expect(version).not.toBeNull();
|
expect(version).not.toBeNull();
|
||||||
expect(version?.version).toBe(3);
|
expect(version?.version).toBe(4);
|
||||||
|
|
||||||
db.close();
|
db.close();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ describe('Best-Candidate Resolution', () => {
|
|||||||
describe('Schema v2 Migration', () => {
|
describe('Schema v2 Migration', () => {
|
||||||
it.skipIf(!HAS_SQLITE)('should have correct current schema version', async () => {
|
it.skipIf(!HAS_SQLITE)('should have correct current schema version', async () => {
|
||||||
const { CURRENT_SCHEMA_VERSION } = await import('../src/db/migrations');
|
const { CURRENT_SCHEMA_VERSION } = await import('../src/db/migrations');
|
||||||
expect(CURRENT_SCHEMA_VERSION).toBe(3);
|
expect(CURRENT_SCHEMA_VERSION).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skipIf(!HAS_SQLITE)('should have migration for version 2', async () => {
|
it.skipIf(!HAS_SQLITE)('should have migration for version 2', async () => {
|
||||||
|
|||||||
+12
-1
@@ -9,7 +9,7 @@ import { SqliteDatabase } from './sqlite-adapter';
|
|||||||
/**
|
/**
|
||||||
* Current schema version
|
* Current schema version
|
||||||
*/
|
*/
|
||||||
export const CURRENT_SCHEMA_VERSION = 3;
|
export const CURRENT_SCHEMA_VERSION = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migration definition
|
* Migration definition
|
||||||
@@ -54,6 +54,17 @@ const migrations: Migration[] = [
|
|||||||
`);
|
`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
version: 4,
|
||||||
|
description:
|
||||||
|
'Drop redundant idx_edges_source / idx_edges_target (covered by source_kind / target_kind composites)',
|
||||||
|
up: (db) => {
|
||||||
|
db.exec(`
|
||||||
|
DROP INDEX IF EXISTS idx_edges_source;
|
||||||
|
DROP INDEX IF EXISTS idx_edges_target;
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+6
-3
@@ -122,9 +122,12 @@ CREATE TRIGGER IF NOT EXISTS nodes_au AFTER UPDATE ON nodes BEGIN
|
|||||||
VALUES (NEW.rowid, NEW.id, NEW.name, NEW.qualified_name, NEW.docstring, NEW.signature);
|
VALUES (NEW.rowid, NEW.id, NEW.name, NEW.qualified_name, NEW.docstring, NEW.signature);
|
||||||
END;
|
END;
|
||||||
|
|
||||||
-- Edge indexes
|
-- Edge indexes.
|
||||||
CREATE INDEX IF NOT EXISTS idx_edges_source ON edges(source);
|
-- idx_edges_source / idx_edges_target are intentionally omitted —
|
||||||
CREATE INDEX IF NOT EXISTS idx_edges_target ON edges(target);
|
-- the (source, kind) and (target, kind) composites below cover the
|
||||||
|
-- corresponding source-only / target-only lookups via SQLite's
|
||||||
|
-- left-prefix scan, so the narrow indexes are dead weight on writes.
|
||||||
|
-- Migration v4 drops them on existing databases.
|
||||||
CREATE INDEX IF NOT EXISTS idx_edges_kind ON edges(kind);
|
CREATE INDEX IF NOT EXISTS idx_edges_kind ON edges(kind);
|
||||||
CREATE INDEX IF NOT EXISTS idx_edges_source_kind ON edges(source, kind);
|
CREATE INDEX IF NOT EXISTS idx_edges_source_kind ON edges(source, kind);
|
||||||
CREATE INDEX IF NOT EXISTS idx_edges_target_kind ON edges(target, kind);
|
CREATE INDEX IF NOT EXISTS idx_edges_target_kind ON edges(target, kind);
|
||||||
|
|||||||
Reference in New Issue
Block a user