摘要
中文分词、GIN 索引和相关性排名是全文检索的三个常见关键词,但把它们接上并不自动得到可用搜索。分词词典、停用词、字段权重、短语规则和排序解释都会改变结果。本文围绕 KingbaseES 全文检索设计一套基线:先固定语料和分析规则,再验证索引覆盖、查询计划与相关性,最后用可回放的样本约束优化方向。
先定义搜索问题
"搜索更准"无法直接验收。先按业务写出查询类型:单词召回、多个词的交集、短语匹配、标题优先、时间衰减和无结果提示。每类准备少量人工标注样本,记录期望命中文档、必须排除的文档以及可以接受的近似结果。
样本要覆盖真实困难:同义词、数字与英文混排、错别字、过短词、专有名词和超长文本。每次修改分词或权重,都用同一批样本回放,比较召回率、前几位准确率、零结果比例和响应时间。没有固定样本,排名变化就只能靠主观感受。
把分词规则当作版本化配置
中文分词器的词典、停用词和自定义词都属于搜索逻辑,应纳入版本控制。新增一个词可能提高专名召回,也可能让常见短语被错误切开。对每个规则变化保留前后分词结果和影响样本,不要只记录"已更新词典"。
字段也要有清晰的分析策略。标题、摘要、正文和标签通常不应完全共用权重;标题中的专名命中可以提高排名,正文中的泛化词则应降低影响。把字段映射写成表格,明确哪些字段建立全文索引,哪些字段只做精确过滤。
GIN 索引要配合查询形状
建立索引前先确认查询是否真的使用全文谓词,以及查询表达式与索引表达式是否一致。把函数包在不同层级、临时拼接语言参数或对字段做隐式类型转换,都可能让优化器无法复用索引。预发环境用代表性数据检查执行计划,关注是否出现大范围扫描和排序落盘。
索引覆盖不等于查询一定快。过滤条件、排序字段和返回列会共同决定成本。对热门查询设置结果数量上限和超时,避免用户输入一个高频词就扫描整个语料。索引重建和词典切换也要评估并发窗口,不能把维护操作与业务高峰重叠。
让相关性排名能解释
相关性分数应拆成可理解的组成:字段权重、词频、文档长度、时间因素和业务过滤。不要直接把一个不可解释的总分展示给产品或排障人员。可以在调试模式返回命中的词、命中字段和各项加权结果,线上只保留必要摘要。
时间衰减要有边界。新文档可以得到加分,但不能让完全不相关的内容因为"新"而排到前面。对标题精确短语、标签命中和正文模糊命中设置不同等级,并为每一级准备反例,防止权重调整只优化了少数查询。
处理中文检索的零结果
零结果时先区分词典没有命中、过滤条件过窄和数据尚未建立索引。系统可以给出放宽建议,但不要偷偷删除用户的时间或权限条件。建议内容来自可追踪的规则,例如移除停用词、使用同义词或改用前缀匹配,并把用户最终选择记录下来供样本回放。
对于敏感字段,检索前仍需执行数据权限过滤。不能因为全文索引返回了某个文档,就绕过租户、部门或行级权限。权限条件要进入查询计划的固定部分,并在测试样本中加入"文本命中但无权查看"的反例。
性能基线要分冷热两类。冷启动关注首次加载词典、连接建立和缓存为空时的延迟;热查询关注缓存稳定后的吞吐与尾延迟。每次测试记录数据规模、并发、返回条数、过滤条件和硬件资源,不能只报一个平均耗时。高峰场景下还要观察索引维护、批量导入与在线查询的相互影响。
查询接口最好把用户意图拆成结构化参数:字段、短语、过滤、排序和页码分别校验,禁止把整段语法直接拼接进 SQL。对排序和分页设置上限,深分页改用稳定游标。这样既便于审计,也能减少恶意输入导致的高成本查询。接口返回的相关性解释应与实际查询版本绑定,避免前端展示过期规则。
基线通过后再引入同义词扩展、拼写纠错或个性化权重。每项优化单独建立实验组,保留对照组和回滚开关;如果某类查询提升而另一类退化,按业务优先级做取舍,并把样本变化写入评测报告。搜索质量是持续迭代的产品能力,不是一次索引创建就结束的数据库操作。
数据导入和索引更新也要纳入基线。批量导入期间可以先写入待索引状态,索引完成并通过抽样校验后再开放查询;增量更新失败时保留失败队列,避免静默丢失文档。删除操作需要区分逻辑删除与物理清理,评测样本中加入已删除文档,确认缓存和索引都不会继续返回它们。
监控面板至少展示查询量、零结果率、前几位点击率、P95 延迟、索引滞后和失败队列长度。告警阈值按查询类型区分,短语查询突然变慢与普通关键词变慢的原因可能完全不同。排障时关联查询版本、词典版本和数据批次,避免只看数据库总 CPU 就下结论。
结语
KingbaseES 全文检索的工程重点不是把分词器和 GIN 索引拼起来,而是建立一条可解释的基线:版本化分析规则,固定评测样本,验证索引与查询形状,拆解相关性分数,并把权限过滤放在召回之前。基线稳定后再做优化,结果才可比较、可回滚,也更容易向业务解释。