← Back to skills
extension
Category: Development & EngineeringAPI key requirement unconfirmed

OceanBase 全文索引调优助手

面向 OceanBase / seekdb 全文索引的性能调优助手:先量化索引构建、分词热路径与 MATCH 查询三段耗时,再按清单定位瓶颈,给出可验证的改动与语义回归方法。

personAuthor: Leona0d00hubOpenAPI

OceanBase / seekdb 全文索引调优

把"全文索引慢"拆成可测量的三段:索引构建、分词热路径、MATCH 查询。不要凭感觉改参数,先拿到 before 数据。

何时使用

  • 建索引(ALTER TABLE ... ADD FULLTEXT INDEX)耗时异常或阻塞业务
  • MATCH(col) AGAINST('...') 延迟高、QPS 低,或带标量过滤时明显变慢
  • 分词器(ik / beng / ngram / ngram2 / space)CPU 占比高
  • 想验证某项优化是否真的带来收益

第一步:量化基线

在 seekdb 仓库中运行统一压测脚本(参数固定后才可横向对比):

cd tools/benchmark
LABEL=before ROWS=20000 BATCH=500 ROUNDS=3000 QUERY_ROUNDS=200 SAMPLES=3 ./fts_large_bench.sh

产出字段分三类,优化时按类别汇总而非只看单项:

| 类别 | 指标 | |---|---| | 构建 | build_ik_all_sec、build_ik_content_sec、build_beng_en_sec | | 分词 | tokenize_ik_avg_ms、tokenize_beng_avg_ms | | 查询 | query_cn_avg_ms、query_beng_avg_ms、query_mixed_avg_ms、query_limit_avg_ms |

计分/验收口径(若参加比赛):三类等权平均,相对基线提升 50% 记满分;单次波动约 2 分,重要结论至少重复 3 次取中位数。

第二步:分段定位

  1. 构建慢:看 build_total_sec 与三个 build_* 的占比。若随文档数线性增长且 CPU 打满,优先并行度与排序;若 CPU 空闲,优先 I/O 与表结构。
  2. 分词慢:单独跑 SELECT tokenize(?, 'ik')。若单次调用 µs 级以上,多为解析器实例反复构造、逐字符分配、停用词表重复加载。
  3. 查询慢:对比 query_*_hits。命中数相近但延迟差异大,说明执行计划或索引选择有问题;query_limit 明显更快说明瓶颈在结果物化而非候选扫描。

第三步:按症状取用优化杠杆

分词器

  • 复用解析器实例(每文档 reset,而不是每次 new),避免重复初始化词典与仲裁器
  • 把逐字符的"取字符 + 判类型"合并为一次调用,减少热循环函数调用
  • 停用词/词典使用进程级只读缓存,按 collation 分组,避免每批次重建
  • 结果容器预分配或使用分块数组,消除逐 token 堆分配

索引构建

  • 提升构建并行度:分区本地构建、按 doc_id 范围切分,避免跨分区 shuffle
  • 排序阶段用 encoded sort key(order-preserving 二进制键),定长键可走基数排序
  • sort key 与 payload 分离,归并只读键,输出时再物化列
  • 复核内存预算:外排阈值过小会导致频繁落盘

查询

  • 确认走了全文索引而不是回表全扫(看执行计划与 hits 规模)
  • 标量过滤条件下推到索引扫描,避免先生成全量候选再过滤
  • LIMIT 场景优先 TopN,避免完整排序
  • 批量/预编译重复查询,减少解析开销

参数与建表

  • min_token_size / max_token_size 与业务语种匹配(英文别用中文默认值)
  • 分词器选择:中文用 ik 或 ngram2,英文用 beng/space,二进制或标识符用 ngram
  • 建索引前先灌数再建(bulk 后再 DDL)通常快于边写边建

第四步:验证与回归

  1. 同一机器、同一 ROWS/BATCH/ROUNDS/QUERY_ROUNDS/SAMPLES 跑 after
  2. 用 LABEL=after SKIP_LOAD=1 复用数据,仅重跑分词与查询
  3. 三类指标分别对比,记录恶化项(性能优化常见"此消彼长")
  4. 语义回归:t/ 下的全文索引用例必须全绿,分词结果与原来逐 token 一致
make -C competition test-hybrid   # PowerContext 侧混合检索回归(如相关)
# seekdb 侧:tools/deploy/mysqltest.py 跑 fts_index 套件

常见坑

  • 只看总耗时:构建、分词、查询混在一起,优化方向会错
  • 忽略预热:首轮含缓存冷启动,至少 WARMUP=30
  • 不同机器/负载下对比:必须同机同参数
  • 改分词规则导致召回变化:性能提升但语义变了,等于没通过
  • 大工具结果/长文本被 Memory 截断:Source 层必须保原文,截断只允许发生在投影或预算阶段

输出模板

场景:<表规模/文档长度/语种/查询形态>
基线:build=X s, tokenize=Y ms, query=Z ms(3 次中位数)
瓶颈:<分段结论 + 证据>
改动:<1-3 条,逐条对应指标>
结果:build/tokenize/query 各自变化 + 语义回归结论
<!-- OB-S:fgUXk45ITvWBSzms1saN0w -->