拼音模糊搜索
一套结构,姓名只是第一个字段
✅ 结论:不动主表,新建 4 张派生表;加字段只插 1 行配置 + 回填 1 次,查询代码不改。
只设计不改代码 · 全部数字为本地实测(10 万员工 × 5 字段造数)
姓名字段零索引,检索全是前导通配
⚠️ 现状每输入一个字就扫一次表,且完全没有拼音能力——中文打错一个字就搜不到。
时延随"命中率"剧烈波动,无法做 SLA;给姓名加索引也救不了——前导通配用不上 B-tree(实测 possible_keys=NULL)。
1 张全局配置表 + 3 张租户派生表
✅ 主表零变更:user_info 不加列、不加索引,避开给每个租户 ALTER 111 列热表。
一句话原则:能整串直接比的放 doc,必须拆开才比得了的放 token。租户表进 copyTables(178 → 181),漏加会静默串租户,已列为静态断言。
应用层解析 → 分级短路 → 分层排序
✅ 数据库只做等值 / 前缀,零特殊功能、零自定义函数。
| 输入 | 走哪层 | 实测 |
|---|---|---|
| 张三丰 | 整串等值 | 0.25 ms |
| 张三(前缀 1.2 万人) | 整串前缀 | 1.2~1.3 ms |
| 三丰(中段) | 2-gram + 校验 | 0.37 ms |
| zhangsanfeng | 全拼等值 | 0.25 ms |
| zsf / zs | 首字母 | 0.25 / 0.29 ms |
| shanchangle(多音) | 位置化 token | 0.7 ms |
| 张丰三(乱序) | 字符升序等值 | 0.31 ms |
| zhangsf(混排·最贵) | 位置化 token | 20~30 ms |
| 无命中(8 档全跑) | 全档 | 23.9 ms |
硬规则:按字段拆多条 SQL(一条 field_code IN (...) 大 SQL 实测计划摇摆,坏计划 2.2 s);召回阶段不 JOIN(JOIN 后 361 ms vs 29.8 ms)。
「字真 > 拼音」保住了,
但「姓名优先」会打架
⚠️ 搜「保安」:部门 19,234 行 + 岗位 14,286 行排在前面,员工「张保安」掉到第 33,521 位。
建议 B:硬要求由第一位 hit_class 保证(两种口径都不变),模型与 SQL 不用改,只改 ORDER BY + 一层 Java 配额。
10 万人 × 5 字段 = 823 MB
✅ 索引占 67%(553 MB)——体积主要花在索引,不是数据。
| 规模 | doc | token | 合计 |
|---|---|---|---|
| 1 万 × 5 字段 | 6.0 万 | 42.4 万 | ≈82 MB |
| 10 万 × 5 字段(实测) | 60.0 万 | 424.0 万 | 823 MB |
| 10 万 × 仅姓名(一期) | 10.0 万 | 96.5 万 | ≈186 MB |
| 50 万 × 5 字段 | 300 万 | 2,120 万 | ≈4.03 GB |
省钱的结论:工号 / 手机号不生成 gram(0 token 行)。11 位手机号若做 gram,一人 21 行,是姓名的 2 倍多,纯浪费。
为什么是 MySQL 派生表
✅ 唯一同时满足「租户物理分表 + 离线可落地 + 加字段零代码 + 零新组件」的路线。
| 维度 | 现状 LIKE | 主表加列 | 本方案 | ES/Meili |
|---|---|---|---|---|
| 拼音/首字母/多音 | 无 | 可 | 可 | 需自建 |
| 字真 > 拼音分层 | 无 | 5 档 | 8 档·字段中立 | 靠 boost |
| 租户物理分表 | 天然 | 每租户 ALTER | 新表入清单 | 需路由 |
| 离线可落地 | 是 | 是 | 零新组件 | 需新运维面 |
| 加字段成本 | — | 加列+DDL | 1 行配置+回填 | 改 mapping |
| 实测时延 | 41~395 ms | 未测 | 0.25~30 ms | 5~20 ms |
甲方原稿的分层思想被完整继承(应用层生成派生值、库只做等值/前缀、CASE 分层),落地形态按 abt 的租户分表改造;它的「3 表 7 索引」在此变成「4 表 15 个索引对象」,差异来自注册表、断点表、幂等唯一键与 2 个整串读音索引。
加一个字段,到底要改什么
✅ 已接入的源表:注册表插 1 行 + 回填 1 次,代码 0 行;索引对象 15 → 15 不变。
| 字段 | 策略 | token/人 | 改动 |
|---|---|---|---|
| 姓名(一期) | 精确+前缀+包含+全拼+首字母+乱序 | 9.65 | — |
| 工号 / 手机号 | 精确+前缀(手机再加后缀) | 0 | 插 1 行 + 回填 |
| 部门(多值) | 精确+前缀+包含+全拼+首字母 | 28.04 | 插 1 行 + 1 个适配器 |
| 岗位 | 精确+前缀+包含 | 4.71 | 插 1 行 + 回填 |
| 标签(多值) | 精确+包含 | — | 插 1 行 + 1 个适配器 |
必须明示的边界:「零代码」只对已接入的源表成立;第一次接一张新表,必然要写 1 个约 20 行的取值适配器。部门这类值域小的字段,二期建议改「实体维」(280 万行 → 2.8 万行,51~85 ms → 0.3 ms)。
异步水位线扫描,≤5 分钟最终一致
✅ 零侵入业务写路径:触发器方案不可行(MySQL 没有汉字→拼音能力),双写会拖慢人员保存。
- 多值表变更(组织/岗位/标签)不会刷新员工时间戳 → 各自按时间扫,命中后整条重算
- 组织改名要 fan-out 该组织下所有人 → 必须限流(一批 ≤1000 人)
- 改名后旧名:≤1 个扫描周期失效,建议接受,不做双写删除
- 兜底:每日一次轻量对账,补时间戳没刷新的漏
60 条可判定条目,门禁 4 条硬线
✅ 判定五档:PASS / FAIL / EXPECTED-FAIL / BLOCKED / KNOWN,退出码只看真 FAIL。
计划稳定性比时延更重要:时延会骗人(现状单字只要 0.25 ms,因为扫到 20 行就停)。「加字段不改代码」用动作证明:真加一个字段 → 代码 diff 为空、索引数不变、召回 SQL 指纹不变。
排期第一风险不是代码,是拼音依赖
⚠️ 仓库、离线仓库、现有工具库都没有拼音能力;自建小字典已被实测证伪(缺字导致全拼搜不到)。
mvn -o 离线可复现;不过 → 一期整体 BLOCKED,排期 +1~3 天需要拍板的只有 5 件
未拍板前按「建议」推进,验收侧记 KNOWN 不记 FAIL;拍板后只切一处开关,不返工。
A:tier 在前 → 「张保安」第 33,521 位,200 条内不可见。B:weight 前移 + 每字段保底 ≥3 条 → 进前 5。
建议 B(模型与 SQL 不用改,只改 ORDER BY + 配额)|甲方 + 产品
精确 COUNT 实测 0.8 ms ~ 2.2 s(看优化器),不可承诺;探测 0.8~1.2 ms。
建议 ≤200 精确 / >200 显示「200+」|产品 + 甲方
开放模糊:一人 +21 行 token、10 万人 +338 MB,且开「猜号」通道。存明文需访问控制与审计,存摘要则排障变难。
建议不开放模糊 + 存明码 + 访问控制/审计|安全 + 甲方(不拍板二期不能开工)
构建机能否取到 jar / 私服能否上传?自建字典已证伪。
建议开工前由运维确认,G0 不过即 BLOCKED|运维 + 甲方
仅在职可搜;一致性 5 分钟为门禁,组织改名 fan-out 10 分钟、时间戳兜底 24 小时作为 KNOWN 宽限。
建议如上,需业务签字|业务(HR)+ 甲方
拍完 5 条,一期即可开工
✅ 设计已闭合:模型、SQL、容量、验收、风险都有实测数字支撑;唯一外部依赖是 G0。
- 甲方/产品:D1 排序、D2 总数、D5 可见性
- 安全:D3 手机号存储面与模糊口径
- 运维:D4 构建机取包 + 离线可复现(不通过则排期 +1~3 天)
本报告只做设计,未改任何代码、未建分支、未提交。数字均为本地实测(10 万员工 × 5 字段造数),非估算。