V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
brader
V2EX  ›  程序员

如何低成本解决模糊搜索问题

  •  
  •   brader · 2022-05-26 17:43:58 +08:00 · 4952 次点击
    这是一个创建于 920 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用的 mysql 数据库,有时候做业务,动不动产品就会说,这个字段我要模糊搜索。 实在不想大费周章,直接用的 like ,前期还好,到了后面跑不动,还有没有其他低成本的替代方案?

    53 条回复    2022-06-01 23:02:39 +08:00
    danbai
        1
    danbai  
       2022-05-26 17:45:40 +08:00
    最近刚好用到了一个搜索引擎,https://www.meilisearch.com/
    Jooooooooo
        2
    Jooooooooo  
       2022-05-26 17:45:42 +08:00
    搞个 es 吧
    brader
        3
    brader  
    OP
       2022-05-26 17:48:07 +08:00
    @Jooooooooo 成本太高了啊,要知道,我们一个后台列表页的需求,按小时算的,就给 2-3 小时工时,去折腾 es ,绩效做不出来
    SjwNo1
        4
    SjwNo1  
       2022-05-26 17:48:41 +08:00
    mysql ngram
    Red998
        5
    Red998  
       2022-05-26 17:50:48 +08:00
    like 的话使用前缀索引好点 、
    Jooooooooo
        6
    Jooooooooo  
       2022-05-26 17:52:32 +08:00
    @brader 那只有改需求一个法子了. 比如只搜一段时间内的, 数据会少点.
    ragnaroks
        7
    ragnaroks  
       2022-05-26 17:52:57 +08:00
    只读从库
    brader
        8
    brader  
    OP
       2022-05-26 17:53:03 +08:00
    @redorblacck886 产品不让,就是要模糊搜索效果
    liaohongxing
        9
    liaohongxing  
       2022-05-26 17:54:15 +08:00
    mysql ngram 全文,最方便的了
    brader
        10
    brader  
    OP
       2022-05-26 17:55:15 +08:00
    @liaohongxing 这个好像方便,如果我用自带的全文索引,不装 ngram 这个插件,模糊查找会出什么问题吗?
    pengtdyd
        11
    pengtdyd  
       2022-05-26 17:56:19 +08:00
    需求评审没人提这个问题 ???
    liaohongxing
        12
    liaohongxing  
       2022-05-26 17:57:07 +08:00
    大哥 ngram 是 mysq8 内置插件。都不需要装 ,支持中文 ,简单几下就配起来的。不想麻烦,就这个最简单 。比 like 强一点
    brader
        13
    brader  
    OP
       2022-05-26 17:58:13 +08:00
    @pengtdyd 那帮蠢货从来不开需求评审,需求时间评估也不让开发评估,都是产品或测试一口价定的时间
    encro
        14
    encro  
       2022-05-26 17:58:14 +08:00   ❤️ 1
    Mysql 中文全文索引(含实例 5 分钟上手)

    https://c4ys.com/archives/2098
    brader
        15
    brader  
    OP
       2022-05-26 17:58:56 +08:00
    @liaohongxing 8 好遥远啊,我们还是 5.6 还是 5.7 来着
    wellerman
        16
    wellerman  
       2022-05-26 18:01:06 +08:00
    简单点就用空间换时间,提取关键词(或全部分词),弄个索引。再顶不住了就只有上 ES 了。
    MoYi123
        17
    MoYi123  
       2022-05-26 18:03:25 +08:00
    换 pg,用 gin 索引
    cowwa
        18
    cowwa  
       2022-05-26 18:10:56 +08:00
    搞个 Redi 缓存起来
    teel
        19
    teel  
       2022-05-26 18:12:29 +08:00 via iPhone
    如果数据量不是特别大的话,把列表内需要搜索的字段全部拉取到前端用 Fuse.js 做模糊搜索。前提是数据量不能太大。
    PS:不让开发评估时间的公司还是尽早走吧
    dzdh
        20
    dzdh  
       2022-05-26 18:16:31 +08:00
    刚在隔壁帖子里看到了个 zinc https://github.com/zinclabs/zinc

    已经在自己的小机器上跑起来了。

    meilisearch 自己测试了 1kw 数据服务器内存撑不住了。

    要长治久安就用 postgresql 吧,装个 zhparser 还能指定分词和词库。
    sadfQED2
        21
    sadfQED2  
       2022-05-26 18:19:06 +08:00 via Android   ❤️ 1
    5.6 5.7 的 mysql ,不用 es ,不用 like ,那你手动拆词,然后在 mysql 里面建一张表当倒排索引?相当于用 mysql 实现一个简易版的 es

    不然的话就找那些奇奇怪怪的 mysql 插件或者存储引擎?但是这种稳定性就不敢保证了

    最后,人和代码有一个能跑就行,没有需求评审,也没有技术评审,上线时间拍脑袋决定,我觉得该你跑了
    Latin
        22
    Latin  
       2022-05-26 18:19:34 +08:00
    上个 elasticsearch 解君忧
    3kkkk
        23
    3kkkk  
       2022-05-26 18:23:41 +08:00
    如果没用过,上面哪种方案用到生产都不是几个小时搞定的。 让产品需求做技术调研,不给时间就让他们自己搞你把上面方案给罗列了。
    Buges
        24
    Buges  
       2022-05-26 18:24:04 +08:00 via Android
    当然是 meilisearch ,简单轻量,适合小规模数据。
    clf
        25
    clf  
       2022-05-26 18:25:05 +08:00
    搜索的时候加上数据量限制?不返回有多少条符合结果的 total 。

    前缀搜索的效率会高很多,能走索引。
    documentzhangx66
        26
    documentzhangx66  
       2022-05-26 18:37:35 +08:00
    模糊搜索本来就是个成本高上天的事情,其成本比分词方案还要高,所以你这出发点就不对。

    你只能采用 有限度的分词 + 主动缓存 + 控制频次的方式,来降低成本,这种思路类似于剪枝,但仍然有一定成本。
    zamaojava
        27
    zamaojava  
       2022-05-26 18:42:16 +08:00
    不直接 run 吗,兄弟,我上家就是给我 精确 crud ,老子直接不干了
    monkeyWie
        28
    monkeyWie  
       2022-05-26 18:52:51 +08:00
    上 es 分词也难搞定,例如搜索一个字的时候
    nox42
        29
    nox42  
       2022-05-26 19:09:31 +08:00
    lucene
    yufeng0681
        30
    yufeng0681  
       2022-05-26 21:26:35 +08:00   ❤️ 4
    产品要快速出效果,3 小时的编码, 就只能用 like ,解决业务功能有无的问题;
    和项目经理说,后续肯定有性能问题,要解决就得技术 leader 上方案,给你们写业务代码的人用,或者单独给时间做这个性能需求。
    至于做不做,那就是项目经理决定。
    makdon
        31
    makdon  
       2022-05-26 22:03:36 +08:00
    看起来开发地位非常工具人呐,代码跟人有一个能跑就行
    westoy
        32
    westoy  
       2022-05-26 22:05:11 +08:00
    跑不动再说吧, like 至少能找到啊.....你分词+fulltext 调教不好, 很多词分错了找都找不到, 更麻烦.......
    marcojbk
        33
    marcojbk  
       2022-05-26 23:34:38 +08:00 via iPhone
    我其实有点没明白你说到了后面跑不动是什么意思,是说查询速度太慢,还是说无法实现比如多词中间加空格搜索的需求?
    brader
        34
    brader  
    OP
       2022-05-27 09:16:40 +08:00
    @wellerman 没有词意概念的,他们不需要分词效果,只要 like 那种模糊效果
    brader
        35
    brader  
    OP
       2022-05-27 09:18:31 +08:00
    @zamaojava 今年跑不了,有购房计划,跑也要过了今年
    brader
        36
    brader  
    OP
       2022-05-27 09:20:02 +08:00
    @marcojbk 用 Like 功能是完全对的,就是数据量多起来了,查询非常慢,我记得那个表,涨到 50 万,就不怎么查的动了
    meystack
        37
    meystack  
       2022-05-27 10:23:12 +08:00
    直接上 ES 或者迅搜,我有写好的类,在我开源的项目 swiftadmin 你在 fork 里面找下之前的备份,可以分分钟使用了,如不是很复杂,建议使用迅搜即可
    tickone
        38
    tickone  
       2022-05-27 13:23:08 +08:00
    可以试试这样查,扫描 name 索引,不是全表扫描,稍微好一点
    select * from table where id in (
    select id from table where name like '%哈哈%'
    )
    markgor
        39
    markgor  
       2022-05-27 14:24:47 +08:00
    这情况,不是应该转移问题吗...?
    前端增加 “等于”/“包含” 让用户选择,当使用包含慢的时候,说这是特性,嫌慢就用等于来筛选;或者搭建 ES 服务....
    让产品自己选择
    lizy0329
        40
    lizy0329  
       2022-05-27 15:06:15 +08:00
    @teel 后端弄个缓存,前端一拉就拉 1w 条数据,应该可以吧
    aikilan
        41
    aikilan  
       2022-05-27 16:05:18 +08:00
    你就在群里告诉产品这样会越来越慢呗,产品要是没意见,后果他就自己承担。
    Features
        42
    Features  
       2022-05-27 16:07:21 +08:00
    啊? 老版 discuz 不是有完善的方案吗?
    1.限制字数
    2.限制搜索频率
    3.必须登录后搜索
    还有很多我都忘记了
    zhangwugui
        43
    zhangwugui  
       2022-05-27 16:08:21 +08:00
    mysql5.7 的 ngram 尝试过,我记得是有点问题的:
    1 )有些高频数据可能搜不到;
    2 )搜索时间可能时快时慢,
    3 )查询条件过长,还可能触发 cache limit ;
    raptor
        44
    raptor  
       2022-05-27 16:09:26 +08:00
    30 楼正解,得让产品知道每个需求都是有成本的,实现模糊查询是一个成本,实现高性能的模糊查询是另一个成本。
    hatsuyuki
        45
    hatsuyuki  
       2022-05-27 16:10:40 +08:00
    小规模数据 meilisearch 最合适,性能高,消耗少
    dog82
        46
    dog82  
       2022-05-27 16:59:31 +08:00
    这个帖子有营养,大家思路好广
    donfisher
        47
    donfisher  
       2022-05-27 17:03:03 +08:00
    1. mysql 做全文索引
    2. 果断上 es
    brader
        48
    brader  
    OP
       2022-05-27 17:09:36 +08:00
    @meystack 请问下你这个迅搜项目,可以有自带组件解决 mysql 表数据的全量同步和增量同步的增删改 同步方案吗?还是要自己通过代码进行推送
    meystack
        49
    meystack  
       2022-05-27 18:21:57 +08:00
    @brader 那没有,如果需要同步的话,有两种方案

    1 、在 PHP 读写的时候,如果有更新可以直接更新迅搜的数据,如果有并发的话就做队列
    2 、自己写 C 扩展去实现,xunsearch 其实就是监听了两个端口,只需要投递和查询相应的数据就行了,
    如果你们技术那边没问题,可以使用 mysql 类似的同步工具,自定义数据结构转换成 XS 对应的东西进行投递更新就行了
    这样可以脱离 PHP ;保持 mysql 同步
    Saxton
        50
    Saxton  
       2022-05-27 23:08:46 +08:00
    小公司不要上 ES ,你确定公司能给你提供好的服务器资源?,到头来资源不够还天天炸,meilisearch 也可以考虑下,如果真想在压低成本就像楼上说的只读从库,也可以考虑 mysql 的分词,虽然不咋样但勉强可以满足需求。
    heyjei
        51
    heyjei  
       2022-05-28 10:36:26 +08:00   ❤️ 2
    当年用 PHP 搞论坛的时候,那时还没有 ES ,分词也没有这么方便。

    PHPBB 有一个骚操作叫基于二分分词的倒排索引,不管是搜索的准确性和速度,效果都很不错。特别适合你这种情况。

    思路就是把一篇文章的按两两分词插入到另外一张倒排索引表,然后搜的时候,把搜索词也二分分词,去查那张倒排表。

    两两分词的意思就是:当年用 PHP 搞论坛的时候 可以分词为:当年、年用、用 P 、PH 、HP 、P 搞、搞论、论坛、坛的、的时、时候。

    适合这种文章的数量比较少的情况。
    zhangwugui
        52
    zhangwugui  
       2022-06-01 10:27:05 +08:00
    @heyjei 这个之前尝试过,这种方式是 分词+倒排索引,最后两张表进行关联,我最近进行测试,发现这种有三个小问题:
    1 )分词表会很大;
    2 )单个汉字进行搜索有问题(可以从产品端避免)
    3 )文章内容有回文的情况查询会有问题;

    中国商标专利事务所有限公司务专

    搜:"专利事务", 查询过滤为:IN ('专利','利事','事务'),能正常搜出来;
    搜:"事务专利", 查询过滤为:IN ('事务','务专','专利'),也能搜出来,但正常是搜不到这条数据;
    heyjei
        53
    heyjei  
       2022-06-01 23:02:39 +08:00
    @zhangwugui 第一个问题其实还好,常用汉字就 2500 字,两两组合也就 6250000 行

    最后一个问题叫 Feature ,智能模糊搜索,>_<
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1077 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 18:28 · PVG 02:28 · LAX 10:28 · JFK 13:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.