第 5 篇:「索引的生命周期」— 从创建到过期,从过期到更新

发布时间:2026/8/19 22:40:35
第 5 篇:「索引的生命周期」— 从创建到过期,从过期到更新 开场:索引不是一成不变的前面我们讨论了 SQLite 的速度、并发控制、降级策略。但有一个基本问题没问:索引的内容从何而来?什么时候更新?怎样保证搜索结果不过期?索引的四个阶段阶段 1: 构建(Build) ├─ 首次启动时 ├─ 扫描所有文件 ├─ 提取符号信息 └─ 填充 SQLite 表 时间:5-21s(一次性) 阶段 2: 稳定(Stable) ├─ 工作中 ├─ SQLite 有效且最新 ├─ 搜索直接用 FTS5 └─ 性能:7ms 时间:大部分时间 阶段 3: 增量更新(Incremental Update) ├─ 用户保存文件 ├─ VSCode 触发 onDidChangeTextDocument 事件 ├─ 后台异步更新改动的文件符号 └─ 数据库逐步更新,用户无感知 时间:改一个文件 ~ 10-50ms(后台) 阶段 4: 过期/重建(Stale/Rebuild) ├─ SQLite 损坏 ├─ 或文件 N 个同时改动(超过更新队列) ├─ 自动检测 └─ 从阶段 1 重来 时间:偶发,通常不触发阶段 1:构建(Build)初始化流程classSQLiteIndexStore{asyncinitialize():Promisevoid{conststartTime=Date.now();console.log('Initializing SQLite index...');// 步骤 1: 检查数据库文件是否存在constdbPath=this.getDbPath();constexists=awaitfs.pathExists(dbPath);if(!exists){console.log('Database not found, creating...');// 步骤 2: 创建新数据库和 FTS5 表awaitthis.createDatabase();// 步骤 3: 扫描工作区constfiles=awaitthis.workspace.getAllFiles();console.log(`Found${files.length}files, extracting symbols...`);// 步骤 4: 批量插入符号awaitthis.indexAllFiles(files);constelapsed=Date.now()-startTime;console.log(`Index created in${elapsed}ms,${this.totalSymbols}symbols`);}else{console.log('Database exists, loading...');// 步骤 5: 打开现有数据库awaitthis.openDatabase();// 步骤 6: 验证完整性awaitthis.validateIndex();console.log('Index loaded successfully');}// 步骤 7: 启动文件监听(增量更新)this.startWatchingFiles();}privateasynccreateDatabase():Promisevoid{awaitthis.db.exec(`CREATE VIRTUAL TABLE code_index USING fts5( id UNINDEXED, name, content, file UNINDEXED, line UNINDEXED, column UNINDEXED, type UNINDEXED, -- function/class/interface/type/const scope UNINDEXED -- global/local/method ); CREATE TABLE IF NOT EXISTS meta ( key TEXT PRIMARY KEY, value TEXT ); INSERT INTO meta (key, value) VALUES ('created_at', ?); INSERT INTO meta (key, value) VALUES ('version', '1.0');`,[newDate().toISOString()]);}privateasyncindexAllFiles(files:File[]):Promisevoid{letcompleted=0;// 批量处理(提高性能)constbatch=100;for(leti=0;ifiles.length;i+=batch){constchunk=files.slice(i,i+batch);// 并发处理本批文件awaitPromise