先说结论在鸿蒙 PC 的 Electron 应用里做本地搜索如果你只盯着查询毫秒数大概率会选错方案。我等下会贴三段能直接跑的代码分别是线性扫描、Fuse.js 和 SQLite FTS5。测下来10000 条案例数据下平均单次查询耗时大概是这个量级方案1000 条5000 条10000 条内存占用线性扫描4.2 ms21 ms45 ms约 12 MBFuse.js0.3 ms1.1 ms2.0 ms约 18 MBSQLite FTS51.8 ms7.5 ms12 ms约 3 MB你看Fuse.js 把 SQLite 按在地上摩擦。但结果你猜怎么着我把项目里的实现换成了 SQLite。先别急着骂我标题党听我把原因说完。等一下这里我漏说一个前提——我说的“本地搜索”不是指输入法那种即时提示而是用户输入关键词后回车触发、需要返回排序结果列表的搜索。这个边界很重要因为两种场景对延迟的容忍度完全不一样。输入法差 50ms 用户都能感知但搜索结果页慢 10ms 基本无感。测试环境也交代一下华为 MateBook 鸿蒙 PC 工程机CPU 是麒麟 9000S 桌面版Electron 版本 33.xNode 22。数据是我从公开渠道整理的一人公司案例库每条记录包含标题、标签、正文摘要平均 180 个汉字。测试前我先把其它进程杀干净避免内存抖动干扰结果。方案一线性扫描。代码写起来最爽一把梭// main/search/linear.tsinterfaceCaseItem{id:string;title:string;tags:string[];content?:string;}exportfunctionlinearSearch(list:CaseItem[],keyword:string):CaseItem[]{constlowerkeyword.toLowerCase();returnlist.filter(itemitem.title.toLowerCase().includes(lower)||item.tags.some(tt.toLowerCase().includes(lower))).slice(0,30);}逻辑够直白吧但这玩意儿有两个暗坑。第一数据一多主进程会被卡死。鸿蒙 PC 上 Electron 的主线程要是阻塞超过 200ms窗口就会出现明显卡顿。我 5000 条数据时搜了一次整个窗口冻结了将近 80ms用户要是正在滚动列表体验直接炸裂。第二它只能做包含匹配搜“鸿蒙”能命中“鸿蒙开发”但搜“鸿蒙发”就凉了。你稍微想做点模糊匹配代码就丑得不像样。方案二Fuse.js。这个库我挺喜欢的轻量、API 友好模糊搜索的效果也确实能打。// main/search/fuse.tsimportFusefromfuse.js;constfuseOptions{keys:[title,tags],threshold:0.35,includeScore:true,limit:30,};exportfunctioncreateFuseIndex(list:CaseItem[]){returnnewFuse(list,fuseOptions);}exportfunctionfuseSearch(fuse:FuseCaseItem,keyword:string):CaseItem[]{returnfuse.search(keyword).map(rr.item);}初始化一次索引后查询速度飞起。问题是Fuse 会把整个索引结构挂在内存里。我测下来10000 条案例数据大概占 18MB 左右。听上去不多但 Electron 主进程的内存本来就被各种框架底层吃得很紧鸿蒙 PC 上再给它加 18MB我那个应用的启动速度肉眼可见地慢了一截。更难受的是每次新增或删除数据你都得重建索引。如果你的数据是离线下载、分批更新的那这个重建过程会让用户感受到明显的卡顿。还有个点很多人会忽略Fuse.js 的索引构建本身也要时间。10000 条数据在我这台鸿蒙 PC 上初始化大概 220ms。也就是说用户每次打开应用都要先等 200 多毫秒把索引塞到内存里搜索才能变快。如果数据还在增长这个等待会越来越长。方案三SQLite FTS5。这是三种方案里最“重”的但也是我最心动的。// main/search/sqlite.tsimportDatabasefrombetter-sqlite3;importpathfrompath;import{app}fromelectron;letdb:Database.Database;exportfunctioninitSearchDB(){constdbPathpath.join(app.getPath(userData),search.db);dbnewDatabase(dbPath);db.exec(CREATE VIRTUAL TABLE IF NOT EXISTS cases USING fts5( id UNINDEXED, title, tags, content ); PRAGMA journal_mode WAL; PRAGMA synchronous NORMAL;);returndb;}exportfunctionupsertCases(items:CaseItem[]){constinsertdb.prepare(INSERT OR REPLACE INTO cases (id, title, tags, content) VALUES (id, title, tags, content));consttagStringify(tags:string[])tags.join( );consttxdb.transaction((rows:CaseItem[]){for(constrowofrows){insert.run({id:row.id,title:row.title,tags:tagStringify(row.tags),content:row.content||});}});tx(items);}exportfunctionsqliteSearch(keyword:string):CaseItem[]{conststmtdb.prepare(SELECT id, title, tags FROM cases WHERE cases MATCH ? ORDER BY rank LIMIT 30);returnstmt.all(${keyword}*)asCaseItem[];}查询 10000 条数据 12ms确实比 Fuse.js 慢。但 SQLite 有三个 Fuse.js 给不了的东西。第一崩溃恢复。WAL 模式下就算用户直接杀进程或者鸿蒙 PC 突然断电数据库文件也不容易损坏。我前面用 Fuse.js 时索引是放在内存里的崩溃后一切归零重启得重新加载。而 SQLite 的数据躺在磁盘上打开即用。第二查询能力。FTS5 支持前缀匹配、短语匹配、布尔组合。用户搜“鸿蒙 NOT 游戏”这种高级语法SQLite 直接能处理Fuse.js 得你自己写过滤逻辑而且效率不一定好。你甚至可以在同一张表上同时做普通过滤和全文搜索代码不用拆成两套。第三增量更新。新增一条案例一条 INSERT 就行不需要重建整个索引。这对数据会持续增长的应用太重要了。我实测批量插入 1000 条数据FTS5 自动维护索引耗时 340ms用户几乎无感知。我实测的那个对比数据是在同一台鸿蒙 PC 上跑了 50 次取的平均值。测试脚本长这样// scripts/benchmark.tsimport{performance}fromperf_hooks;exportfunctionbench(name:string,fn:(kw:string)unknown,keyword:string,rounds50){// 预热for(leti0;i5;i)fn(keyword);conststartperformance.now();for(leti0;irounds;i)fn(keyword);constms(performance.now()-start)/rounds;console.log(${name}:${ms.toFixed(2)}ms/次);}跑之前记得把better-sqlite3在鸿蒙 PC 上重新编译一遍。我踩过的坑是直接用 npm 装好的预编译二进制在鸿蒙定制内核上会报NODE_MODULE_VERSION不匹配必须走electron-rebuild。命令大概是npmrun electron-rebuild ---f-wbetter-sqlite3如果你的 CI 环境还没有鸿蒙 PC 的交叉编译链这一步能卡你半天。我建议先在真机上编一次把产物提交到仓库后面就不用每次都折腾。那到底怎么选我直接给判断标准不按编号想到哪儿说到哪儿。如果你数据量不到 500 条或者搜索需求就是简单的标题匹配Fuse.js 更合适。启动快、代码少、效果柔和用户输入体验也好。SQLite 这套方案重就重在它给你留了后路。如果你数据会增长或者需要离线稳定、崩溃不丢数据直接上 SQLite。别被那 10ms 的差距迷惑真实用户根本感觉不出来。倒是应用 crash 后索引没了用户下次打开要重新等 200ms 建索引那才叫恼火。顺带一提我做的 App 雷达鸭鸿蒙版已上架华为应用市场里那个案例搜索功能最终用的就是 SQLite FTS5 这套方案。反正我现在做 Electron 跨端项目本地搜索这块基本不会选 Fuse.js 做主存储方案了。毫秒数好看但扛不住数据增长和异常场景。你目前在 Electron 项目里用的是什么搜索方案遇到过类似的选择纠结吗关于作者老三10 年以上软件开发经验软件设计师、人工智能应用工程师。目前专注鸿蒙应用开发ArkTS北向开发与 Web 前端也在折腾 AI 自动化。不定期在 CSDN 分享鸿蒙和 AI 方向的技术文章。本文遵循 MIT 协议转载请注明出处。