应用java实现相似度打分改进sql语句的like功能
一、sql语句的痛点s.sku_name LIKE CONCAT(%, #{name}, %)OR g.goods_name LIKE CONCAT(%, #{name}, %)...本质是连续子串匹配所以场景数据库存用户输入LIKE 能否命中原因有空格红富士苹果红富士 苹果❌红富士 苹果不是连续子串中间掉字农夫山泉矿泉水农夫矿泉水❌中间缺山泉非连续顺序颠倒苹果12手机手机苹果❌顺序不对方式 1MySQL 原生 ngram 全文索引最省事DB 层搞定MySQL 内置了 CJK 的ngram分词器ALTER TABLE wms_goods_sku ADD FULLTEXT INDEX ft_sku_name (sku_name) WITH PARSER ngram;-- 查询WHERE MATCH(sku_name) AGAINST(农夫矿泉水 IN BOOLEAN MODE)数据库自动按字符 n-gram 建索引你一行 Java 分词都不用写还有索引加速。适合做粗召回。我目前用的是这样的WHERE s.del_flag 0AND ( s.sku_name LIKE %农夫% OR g.goods_name LIKE %农夫% OR ...OR s.sku_name LIKE %夫山% OR ... ) -- 每个 bigram 一组 OR前导通配用不上普通 B-Tree 索引本质是全表扫描。所以多个 bigram 的 OR→ 每行都要跑一遍所有 LIKE比原来单个 LIKE 更重。数据量小时单租户几百~几千 SKU→ 毫秒级完全无感不需要额外索引。数据量大时单租户几万~几十万 SKU→ 会明显变慢。是否需要加分词索引分规模看单租户 SKU 量级当前 LIKE-OR 方案建议 5 千毫秒级不用加保持现状5 千 ~ 5 万几十~几百 ms建议上 ngram 全文索引 5 万可能 1s必须上 ngram 或独立搜索引擎如果要优化MySQL ngram 全文索引MySQL 内置 CJK 的ngram分词器可以把召回从全表扫描变成索引命中ALTER TABLE wms_goods_sku ADD FULLTEXT INDEX ft_sku_name (sku_name) WITH PARSER ngram;ALTER TABLE wms_goods ADD FULLTEXT INDEX ft_goods_name (goods_name) WITH PARSER ngram;召回 SQL 改成WHERE MATCH(s.sku_name) AGAINST(农夫矿泉水 IN NATURAL LANGUAGE MODE)核心算法换成了成熟类库委托Hutool 5.8.25 的cn.hutool.core.text.TextSimilarity进行相似度打分可在苹果应用市场搜索“羽辽进销存”免登录体验相似度打分实践应用。PC端https://zhicun.site