V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
enjoychen0318
V2EX  ›  程序员

百万级数据的模糊查询,求方案

  •  
  •   enjoychen0318 · 2022-01-08 19:07:29 +08:00 · 3739 次点击
    这是一个创建于 1075 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有一张 mysql 的 data 表有 300 个 varchar 字段:value1 到 value300 ,想要支持模糊查询,
    想到的办法是建立一张索引表,

    id, 
    data_id, data 表的 id
    number, 数据在 data 表中的位置
    value, 数据的值
    

    然后加上索引 data_id,number,value ,但是这样只能加速前缀匹配

    现在有个想法,比如value 等于"abcdefghi" 就往 index 表插入以下数据,

    abcdefghi,
    bcdefghi,
    cdefghi,
    defghi,
    ...
    

    这样就能支持 "%ced%"的快速查询了, 但是数据量会很大,data 表数据百万的话,可能 index 就几十亿了,这种方案可行么?

    大家有没更好的方案?比如说 index 表 用 elasticsearch?

    15 条回复    2022-01-10 11:04:26 +08:00
    damai0419
        1
    damai0419  
       2022-01-08 19:17:26 +08:00
    mysql 有个全文检索索引。你可以调研下,能不能支持百万级数据。估摸着可以用。
    qaweqa
        2
    qaweqa  
       2022-01-08 19:19:53 +08:00
    试试用 instr()
    enjoychen0318
        3
    enjoychen0318  
    OP
       2022-01-08 19:36:51 +08:00   ❤️ 1
    @damai0419 如果用全文索引我感觉 elasticsearch 会好很多,但是全文索引的分词会导致有些搜索不准确吧
    enjoychen0318
        4
    enjoychen0318  
    OP
       2022-01-08 19:37:29 +08:00
    @qaweqa 试了下。。百万行的数据查询好像和 like 差不多
    cha0sCat
        5
    cha0sCat  
       2022-01-08 20:08:39 +08:00
    pg 有一个 pg-trgm 索引的原理和你说的差不多
    基本是把关键词 'abcd' 拆分成 ' a' ' ab' 'abc' 'bcd' 'cd ' 这样查询
    outdoorlife
        6
    outdoorlife  
       2022-01-08 20:15:12 +08:00
    @enjoychen0318

    我同意你的用 ELK 来做

    另外可以考虑直接做个只读库,只干这种非实时操作的。这是我们在没有 HADOOP 没有 ELK 的 2015 年前最常见的也是最有效的办法。

    包括未来你要做数据 ETL 你也不可能主库抽,抽一次主库死了,只从从库抽。
    zhoudaiyu
        7
    zhoudaiyu  
       2022-01-08 20:44:18 +08:00 via iPhone
    不知道 Loki 能不能 cover 这种场景
    tinybaby365
        8
    tinybaby365  
       2022-01-08 21:20:37 +08:00
    优先用 elasticsearch ,想省钱就用 postgres 。
    dusu
        9
    dusu  
       2022-01-09 02:49:48 +08:00 via iPhone
    manticoresearch 中小企业全文搜索伴侣
    WhereverYouGo
        10
    WhereverYouGo  
       2022-01-09 13:11:23 +08:00
    ES ,字段用 ngram 分词器,匹配时用 match_phrase 语句。
    ferstar
        11
    ferstar  
       2022-01-09 15:18:10 +08:00 via Android
    才百万,pg gin 索引了解下
    ospider
        12
    ospider  
       2022-01-09 19:02:23 +08:00
    才百万……命令行用 fzf 都行
    SmiteChow
        13
    SmiteChow  
       2022-01-10 09:25:34 +08:00
    瞧不起 mysql 的索引吗?如果字段没有超过 255 字符,mysql 模糊查找没有任何问题。

    超过了就不合适了,看你的描述也不需要分词那就上 mongodb 。
    DollarKiller
        14
    DollarKiller  
       2022-01-10 09:51:06 +08:00
    MoYi123
        15
    MoYi123  
       2022-01-10 11:04:26 +08:00
    你的想法叫做"后缀数组" https://oi-wiki.org/string/sa/
    不过不需要把字符串真的完全切开,只需要存从 0,1,2,3... 开始的字符串的 rank 值即可, 查的时候用二分查找,
    生成的时间复杂度是 O(n),查找是 O(m * log(n)), (n 是整个字符串的长度,m 是查询串的长度)
    如果你很想在工作的代码里整活的话也不是不能用.

    当然, 用上面说的各种方案肯定是更加靠谱的.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3316 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 11:58 · PVG 19:58 · LAX 03:58 · JFK 06:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.