因为做系统时用到了模糊查询,涉及到了全文搜索的问题,这里分享下经验
我们先定义什么是全文搜索的难题
做数据库查询时,随着数据量的增大,性能也会随之下降。
使用索引,可以使查询不至于在全部数据中遍历,从而保证查询速度可以接受 就是说你有 500 万条数据时,加 where 条件,会使数据库去逐行对比 500 万条数据每一行数据的值,非常耗时 加了索引后,直接就能筛选出满足 where 条件的记录,不需要进行遍历,使用 explain 就可以看到 SQL 对比的条数
但是在做文本的搜索时,经常要模糊查找,比如搜索 "订单" 时,我们希望得出 "采购订单", "订单出库" 这两条记录 最直接的方法是在 where 里写 like %条件% 这个时候,分两种情况讨论。
当 % 在后面时,索引能够保证遍历的数据量是符合以关键字开头的记录的数量,这种情况下,索引能有效减少对比的条数 而当 % 在前面时,由于不知道怎么缩小结果范围,因此依然会遍历整个表,这种情况在索引无效 也就是说最简单的做法是直接写 where like 条件% 这样当然满足不了我们的要求,搜索 "订单" 时,无法得到 "采购订单" 的记录
这个时候就是全文搜索派上用场的地方。也就是说,全文搜索是用于在大量数据中做模糊查询的优化方法 接下来是正题,如何做全文搜索,具体而言,如何在 MySQL 里做全文搜索
从 MySQL 5.0 后支持一种 FULLTEXT 的索引类型(innodb 在 5.6 以后支持),在需要模糊查询的列中,建立这个索引就可以支持全文搜索 where 条件的写法不是 like 而是 match() ... against
但是,中文的分词与英文不一致,英文使用空格分词,中文由语义进行分词,因此默认情况下全文搜索无法在汉字里搜索 这个时候需要手动指定一个分词器 ngram,这个在 MySQL 5.7 中被 innodb 支持,
需要这样建立索引: ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER ngram; 查询时这样写: SELECT * FROM articales WHERE MATCH(body) AGAINST("keywords" IN BOOLEAN MODE);
这样 sql explain 时就可以看到影响的 rows 仅为 1,证明我们没有进行全表的遍历 结论: 全文搜索是在模糊查询时进行优化的一个手段,当需要在大量数据中搜索子串时能够提高性能。
比如可以加快搜索产品名称中的 "硫酸脲" 的速度。不过这也是在大量数据的前提下的,如果要进行全文搜索的表不到 10 万行,直接使用 %like% 也可以接受。
仅此记录他言--