一个线上全文索引BUG的排查:关于类阿拉件数字的分词与检索
2023-05-18 14:33:04 作者:admin
说到全文检索的分词,多半讲到的是中(日韩)文分词,少有英文等拉丁文系语言,因为英语单词天然就是分词的。
但更少讲到阿拉伯数字。比如金额,手机号码,座机号码等等。
以下不是传统的从0开始针对mysql全文索引前世今生讲起。
我更喜欢从一个小问题入手,见缝插针的将相关的知识点,以非时间线性顺序零散穿插起来。
从一个线上的BUG说起
我们有一张人口表,里面的数据有多种数据源合并而来,因此每个用户的手机号可能有多个。
这也很好理解,有的人就是有多个手机号,有的人就是经常换手机号,对吧。
现在有个功能需要通过手机号去关联用户。
因为手机号有多个,所以要么使用like进行模糊匹配。用户表有上千万条记录,这样的效率肯定是不能接受的。
select * from t_user where phone like '%13112345678%'
要么使用另一个折中的方案,将手机号单独成表,用户表对手机号表一对多关联。
这种方式效率上能接受,但需要改变现有数据结构,故放弃。
select u.id,u.username,u.phone from t_user u LEFT JOIN t_user_phone p on u.id = p.user_id where p.phone = '13112345678'
最终选用全文索引。(mysql 5.7.6+)
先在用户表针对手机号创建一个全文索引。
使用内置分词引擎ngram
。
CREATE FULLTEXT INDEX idx_full_text_phone ON t_user (phone) WITH PARSER ngram;
当使用手机模糊查询关联用户时可使用以下语句。
- 布尔模式模糊检索
select * from t_user where match(phone) AGAINST('13996459860' in boolean mode)
- 自然语言模式。mysql默认为此模式,所以第2条sql没有显式指定时,仍然为自然语言模式。
select * from t_user where match(phone) AGAINST('13996459860' in NATURAL LANGUAGE mode)或select * from t_user where match(phone) AGAINST('13996459860')
根据我们的需求,查询手机号需要全匹配才算命中。所以选择布尔模式。
自然语言模式做不到。
关于布尔模式和自然语言模式的区别,后面做介绍。
以上算是简单的背景介绍。
但是
万恶的但是,虽迟但到
有一天产品过来告诉我,某个手机号关联出来上百个人。
他问,这种情况是正常的吗?
他如果直接说你这里有个bug,我可能直接就怼回去了(bushi
猜你喜欢
联络方式:
400-123-789
邮箱:xiachao@163.com
Q Q:12345678
微信公众号
微信二维码