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

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

  •  
  •   brader · 309 天前 · 3269 次点击
    这是一个创建于 309 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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