思源笔记 v3.7.1 技术解读:FTS5 索引去重、空闲自动修索引与移动端体验改进

发布时间:2026/9/10 8:25:13
思源笔记 v3.7.1 技术解读:FTS5 索引去重、空闲自动修索引与移动端体验改进 思源笔记 v3.7.1 技术解读FTS5 索引去重、空闲自动修索引与移动端体验改进【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan导读思源笔记SiYuanv3.7.1 是一个以细节打磨为主的版本blocks_fts全文索引改为 FTS5 external content 模式以消除数据冗余新增用户空闲时自动订正索引机制同时修复了 PDF 内文本搜索失效、数据库分组后无法新增字段等一批高价值问题。本文以官方变更日志为骨架结合本仓库源码逐一剖析这些改动的实现原理、触发条件与影响面帮助读者理解思源底层索引架构与本次升级的实战价值。本文内容依据 app/changelogs/v3.7.1/v3.7.1.md源码分析均来自当前仓库。一、版本概览与变更结构v3.7.1 共包含三大类变更Enhancement增强21 项覆盖全文索引架构、索引维护、集市、Markdown 导入、Electron 行为、移动端交互等Bugfix缺陷修复11 项重点包括 PDF 搜索、数据库字段过滤、数据库视图同步、安全漏洞等Document文档1 项新增工作空间文件系统布局文档。其中最值得开发者关注的是两项底层架构级改动blocks_fts采用 FTS5 external content 模式与blocks表去重存储用户空闲时自动执行索引订正index fixing。下面逐一深入。二、全文索引架构升级blocks_fts 改用 FTS5 external content 模式2.1 改动目标与 blocks 表去重官方变更日志Use FTS5 external content mode for blocks_fts to deduplicate data with blocks思源将每个块的内容同时写入blocks表结构化数据与blocks_fts虚拟表全文检索倒排索引两个表之间长期存在一份数据的物理冗余。本次升级将blocks_fts切换为 FTS5 的external content 模式FTS 表不再物理存储各列值仅维护倒排索引原始内容由contentblocks指向的blocks表按rowid回表提供。2.2 源码实现建表语句与核心约束在 kernel/sql/database.go 的initFTSBlocks()中可以看到完整建表逻辑// 采用 external content 模式blocks_fts 不再物理存储列值仅维护倒排索引 // 原文由 content 指向的 blocks 表提供按 content_rowidblocks 的隐式 rowid回表取值。 // 因此 FTS 行的 rowid 必须与 blocks 行的 rowid 严格一致所有写路径需显式传 rowid。 _, err db.Exec(CREATE VIRTUAL TABLE blocks_fts USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath UNINDEXED, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, contentblocks, content_rowidrowid, tokenize\ ftsTokenize() \))关键点解读contentblocks声明外部内容表为blockscontent_rowidrowid指定以blocks的隐式 rowid 作为回表键可检索列name、alias、memo、tag、content、fcontent、ial保持索引其余元数据列标记为UNINDEXED分词器由ftsTokenize()动态注入即思源自研的siyuan分词支持中英文混合与大小写折叠。该模式的核心约束是FTS 行与blocks行的 rowid 必须严格一一对应因此所有写入路径都必须显式携带 rowid。这一点在 kernel/sql/upsert.go 的注释与BlocksFTSInsert语句中明确体现// blocks_fts 采用 external content 模式contentblocks写入时必须显式提供 rowid BlocksFTSInsert INSERT INTO blocks_fts (rowid, id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated) VALUES %s同时 kernel/sql/block.go 规定局部更新索引列的路径updateRootContent、updateBlockContent、indexNode必须先写blocks_fts、再写blocks保证回表取值前倒排索引已就绪。2.3 索引重建方式的变化external content 模式下重建索引不能再使用INSERT ... SELECT FROM blocks那样 FTS 会自分配 rowid 导致与blocks脱钩必须使用 FTS5 内建命令func RebuildFTSIndex() (err error) { if err initFTSBlocks(); err ! nil { return } // external content 模式下使用 rebuild 命令重建索引 // FTS5 会扫描 blocks 表并用 blocks 的 rowid 作为 FTS rowid保证两者对齐。 stmt : INSERT INTO blocks_fts(blocks_fts) VALUES(rebuild) _, err db.Exec(stmt) return }对应 kernel/sql/database.go。当手动触发重建索引POST /api/system/rebuildDataIndex见 kernel/api/router.go或RebuildFTSIndex失败回退全量重建kernel/model/box.go时都会走到这条路径。2.4 性能基准测试验证仓库新增了专门的基准测试 kernel/sql/fts_bench_test.go量化 external content 模式contentblocks, content_rowidrowid与旧标准模式的写入、查询、重建开销差异。测试中对比了两套建表 DDL 与两套写入逻辑标准模式成对写blocks与blocks_ftsexternal 模式显式带 rowid 写入可直接作为评估该改造收益的参考依据。实战提示本次升级会在启动时重建blocks_ftsinitFTSBlocks会先DROP TABLE IF EXISTS blocks_fts。升级后首次启动会有一段重建索引时间属预期行为索引重建完成后全文搜索内容、名称、别名、标签行为与之前一致但数据存储冗余显著降低。三、空闲自动订正索引AutoFixIndex 的触发与流水线3.1 改动目标官方变更日志Automatically perform index fixing during idle time此前索引订正index fixing仅在数据同步完成后执行一次checkIndex若订正被中断或出现遗漏索引与文件系统会长期不一致。v3.7.1 引入AutoFixIndex当用户空闲、且存在未订正变更dirty 标志时自动补齐索引订正。3.2 触发条件三重门槛 双检锁实现位于 kernel/model/index_fix.go由 cron 每分钟调用门槛常量说明空闲阈值idleFixThreshold 7 * time.Minute用户连续空闲超过 7 分钟才允许触发脏标志util.IsIndexFixDirty()存在未订正的变更dirty才需要跑冷却期fixCooldown 120 * time.Minute上次订正完成后至少间隔 120 分钟才能再次触发func AutoFixIndex() { defer logging.Recover() if util.IsMobileContainer() { return } // 移动端不执行 if !util.IsIdle(idleFixThreshold) { return } // 空闲不足 7 分钟 if !util.IsIndexFixDirty() { return } // 无脏数据 if !lastFixedAt.IsZero() time.Since(lastFixedAt) fixCooldown { return } if !fixIndexMu.TryLock() { return } // 非阻塞避免与 checkIndex 并发 defer fixIndexMu.Unlock() // double-check拿到锁后再确认一次确实空闲 if !util.IsIdle(idleFixThreshold) { return } logging.LogInfof(start auto fixing index on idle...) runFixIndexPipeline() }设计要点fixIndexMukernel/model/index_fix.go保证checkIndex与AutoFixIndex互斥不会并发跑同一套订正TryLock非阻塞若校验正在运行则直接跳过本次不堆积 goroutine加锁后二次确认空闲避免等待锁期间用户重新开始操作导致订正与用户编辑冲突移动端容器util.IsMobileContainer()明确跳过与同步后校验行为保持一致见 kernel/model/index_fix.go。3.3 订正流水线五步 fixIndexPipelinecheckIndex与AutoFixIndex共用同一流水线fixIndexPipelinekernel/model/index_fix.go每一步之间sql.FlushQueue()冲刷写入队列removeDuplicateDatabaseIndex删除数据库索引中的重复树按blocks/blocks_fts查重重复 root 走BatchRemoveTreeQueueresetDuplicateBlocksOnFileSys扫描.sy文件重置重复块 ID、无效文件名自动清理遗留的history文件夹对未解锁的加密笔记本跳过避免密文被误当损坏数据移走fixBlockTreeByFileSys以文件系统为准订正块树——清理冗余块树、补齐缺失块的索引fixDatabaseIndexByBlockTree对比块树与数据库的updated时间戳超过 10 分钟偏差即重索引并清理数据库中已不存在的树removeDuplicateDatabaseRefs删除重复的数据库引用关系。流水线全程通过状态栏推送进度util.PushStatusBar按 1/5 ~ 5/5 步进完成后util.MarkIndexClean()清除脏标志并记录lastFixedAt进入冷却期kernel/model/index_fix.go。实战提示该机制是自动养护型设计——升级后无需任何配置在用户离开键盘 7 分钟以上、且存在索引脏数据时自动触发用户回来操作会立即被打断吗不会因为触发前有双重空闲确认且订正与用户操作互斥。若想主动检查索引状态可通过状态栏进度提示观察。四、增强项逐条拆解从 URI 到移动端交互4.1 集市支持 siyuan://bazaar/{type}/{name}/readme URI新增 URI 协议siyuan://bazaar/{type}/{name}/readme用于直接打开集市bazaar某类包{type}plugin/widget/icon/theme/template 等的 README。后端支撑来自 kernel/api/bazaar.go 的getBazaarPackageREADME接口参数repoURL、repoHash、packageType并对packageType做了白名单校验以及 kernel/bazaar/readme.go 的GetBazaarPackageREADME候选 README 文件名按当前语言首选 → default → README.md优先级去重getReadmeFileCandidates见 kernel/bazaar/readme.go在线拉取失败时依次回退候选文件全部失败则返回错误拼接信息兼容 UTF-16 LE/BE BOM 编码通过 Lute 引擎渲染 Markdown 为 HTML并对代码块注入code-block类名、统一资源链接基准linkBase。4.2 Markdown 导入解析 audio/video 标签Improve Markdown import to parse audio/video tags使 Markdown 导入能正确识别audio、video标签并转为思源对应的音频/视频块。这延续了 kernel/model/import.go 中以 Lute 解析并转换节点的既有导入管线属于导入能力补齐。4.3 Electron 与 Windows 行为禁用混合内容自动升级 HTTPSPR 17994Electron 应用中关闭 mixed content 的自动 HTTPS 升级避免本地 HTTP 资源如http://127.0.0.1内嵌内容被强制升级后加载失败Microsoft Store 版隐藏自动更新选项Issue 17997商店版更新由商店托管隐藏内置自动更新入口避免双重更新机制冲突。4.4 编辑器与文档操作块引用的 padding 区域支持拖拽选择Issue 15331从内容左、右、底部留白处开始框选文本改善选择起始点的容错通过块引用新建文档的流程优化PR 18065Improve new document creation via block references in the editor块引用锚文本未变化时跳过引用文档持久化PR 18066Skip persisting referencing docs when block ref anchor text is unchanged——锚文本不变就不重复写引用文档减少无谓的文档写入与索引更新固定表头的表格输入不再重置滚动位置Issue 18035修复带固定表头表格中编辑时滚动位置跳变的体验问题。4.5 移动端 / 触屏交互横向超级块列宽铺满Issue 14212移动端横向超级块中列应占满整行宽度HarmonyOS 与 Android 桌面模式自动弹出屏幕键盘Issue 18028长按并纵向滚动不再误触发多选模式Issue 18045iPhone 上设置页从左到右选择文本不再意外关闭页面Issue 18043iPhone 上块 gutter 缺失、无法扩展选区Issue 18055修复移动端 flashcard 中块标志栏缺失问题iOS 分享面板缺少思源选项Issue 18056修复 iOS 系统分享目标未注册问题移动端左侧边栏头部改进Issue 18003将块拖到浮动文档树时 Dock 面板不出现Issue 18033修复拖拽到浮动文档树区域时停靠面板无响应。4.6 输入法 / 键盘macOS 删除不完整拼音时光标跳转其他单元格Issue 17584修复中文输入法候选状态删字时编辑器光标错乱的问题。五、Bugfix 深挖PDF 搜索与数据库修复5.1 PDF 文件内文本搜索失效Issue 17941Cannot search text within PDF files修复了 PDF 内文本无法被全局搜索命中的回归问题。思源的全文检索覆盖资源文件PDF内容其实现路径在 kernel/sql/asset_content.go 与 kernel/sql/asset_content_query.go资源内容入库与查询底层依赖 PDF 文本抽取kernel/model/pdf.go。本次修复使 PDF 文本重新进入索引队列用户可在搜索面板中检索到 PDF 内的关键词。5.2 数据库属性视图相关修复分组后无法新增字段Issue 18004修复数据库分组视图下新增属性字段入口失效Created time字段过滤不生效Issue 18017修复按创建时间筛选无效的问题涉及 kernel/av/av.go 中属性视图过滤逻辑见 kernel/av/filter.go滚动加载相关问题Issue 18010修复数据库表格滚动加载的异常双端同时打开时数据库视图无法同步Issue 18027修复多设备同时在线时数据库视图状态不同步。5.3 其他修复启动时偶发卡在 Finishing bootIssue 18008修复特定场景下启动收尾阶段的挂起与启动时的索引/队列任务调度相关列表块转段落再撤销出现异常Issue 18012修复块类型转换后撤销历史状态错乱iOS 图片不显示Issue 18013、部分 Android/iOS 设备索引问题Issue 18014移动端资源加载与索引队列的针对性修复块图标菜单在窗口左边缘被裁剪Issue 18024修复菜单定位溢出部分安全漏洞修复Issue 18032未公开细节的安全补丁建议尽快升级。六、文档更新工作空间文件系统布局v3.7.1 新增官方文档Workspace File-System LayoutIssue 18007系统讲解工作空间目录结构data/、conf/、widgets/、plugins/、themes/、storage/、temp/等。仓库内对应文档位于 docs/WORKSPACE.md含 docs/WORKSPACE.zh-CN.md 中文版可作为理解思源数据落盘与备份策略的一手资料。七、升级建议与影响评估关注点说明首次启动耗时升级后blocks_fts会重建external content 模式首次启动索引重建耗时略增属预期磁盘占用FTS 表不再物理存列值blocks与blocks_fts数据去重长期看数据库体积下降索引一致性空闲自动订正机制兜底7 分钟空闲 dirty 标志 120 分钟冷却期自动运行无需人工干预移动端同步后校验与空闲订正均跳过移动端容器移动端依赖同步后的一次性校验安全包含安全漏洞修复Issue 18032建议及时升级至 v3.7.1 及以上版本总结v3.7.1 表面是细节改进实则暗含一次重要的存储架构调整FTS5 external content 去重与索引自愈机制的落地。对于深度用户理解blocks_fts的 rowid 对齐约束与空闲订正的触发条件有助于排查搜索/索引类问题对于开发者kernel/sql/database.go、kernel/model/index_fix.go 与 kernel/sql/fts_bench_test.go 是学习 SQLite FTS5 external content 实战用法的高质量范本。【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询