2000W 个不重复的 32 位长字符串存于 mysql 中,现在怎样判断该数据表中存在某个特定值? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
Reign
V2EX    程序员

2000W 个不重复的 32 位长字符串存于 mysql 中,现在怎样判断该数据表中存在某个特定值?

  •  
  •   Reign 2017-02-15 17:38:20 +08:00 4291 次点击
    这是一个创建于 3239 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前的业务逻辑是,有 2000W 个 32 位长字符串存在 mysql 中,该 mysql 表就只有 2 个字段,自增 id 和 hash ,现在要验证这个表中是否存在某个 hash 值,怎样用最简单快速的方法查询?我想到过用 redis 来存,但是内存吃不消,有没有好的解决方案?谢谢

    37 条回复    2017-04-15 21:57:32 +08:00
    eote
        1
    eote  
       2017-02-15 17:39:22 +08:00
    排序+binary search
    eote
        2
    eote  
       2017-02-15 17:40:29 +08:00
    或者 bitmap
    forestyuan
        3
    forestyuan  
       2017-02-15 17:44:57 +08:00
    建个索引然后用 SQL 查询就行了吧
    withlqs
        4
    withlqs  
       2017-02-15 17:46:09 +08:00
    字典树
    Reign
        5
    Reign  
    OP
       2017-02-15 17:46:57 +08:00 via iPhone
    @forestyuan 感觉有点慢 硬盘很渣
    allenhu
        6
    allenhu  
       2017-02-15 17:47:44 +08:00
    加多一列 crc ,存 crc32 ( hash ),然后 加 index idx_crc(crc32),配合缓存,速度不会太慢。
    freeminder
        7
    freeminder  
       2017-02-15 17:48:06 +08:00   1
    bloom filter?
    liuxu
        8
    liuxu  
       2017-02-15 17:49:04 +08:00
    这。。该 hash 分表了,根据 hash 最后 2-3 位分成 100-1000 个表。
    XiaoFaye
        9
    XiaoFaye  
       2017-02-15 17:49:13 +08:00
    @Reign 升级硬件能解决的问题,绝对不要浪费技术人员的时间。极有可能所花时间的价值已经远远超过硬件的价值。
    w2exzz
        10
    w2exzz  
       2017-02-15 17:49:28 +08:00
    显然是再增加一列啊……这一列保存 hash 值…… hash 值留 8 位就行了

    然后搜索的时候先匹配 hash 值,匹配到了再匹配全部内容。都一致就找到了。
    hash 不一致就 pass
    forestyuan
        11
    forestyuan  
       2017-02-15 17:56:20 +08:00
    如果自己写算法,一来容易有 BUG ,二来也不一定比数据库引擎优化的好。
    Michaelssss
        12
    Michaelssss  
       2017-02-15 18:00:00 +08:00
    2000W 好像建个索引就完事了。。。。这数据量不大。。。 5~10MS 都出来了。。。
    redis 你没必要全部扔进去啊,- -查询成功一次扔一次,缓存成功就直接走缓存,缓存失败再去 mysql ,这才是缓存的意义啊
    Michaelssss
        13
    Michaelssss  
       2017-02-15 18:02:28 +08:00
    如果要自己写算法就是 boolean filter
    jianzhiyao020
        14
    jianzhiyao020  
       2017-02-15 18:14:26 +08:00
    建索引啊,有这么复杂?
    cloudzhou
        15
    cloudzhou  
       2017-02-15 18:21:07 +08:00
    @allenhu 方法可行

    另外有一个取巧的方法,需要更改一下业务:
    就是 hash 里面隐含着 id

    我详细解释一下,比如在生成 hash 的时候(大部分是随机值)
    hash 值为空,先 save 一下,得到自增 id ,比如 1000 ,然后简单的用 36 进制表示,就是 rs
    然后命名规则如下:
    1 位是表示 36 进制长度 + N 位是 36 进制值 + ( 32-1-N )位随机值

    然后 update set hash = '...' where id = 1000 更新进去

    例子,比如 1000 ,那么表示为 2rs...
    这样, hash 里面直接可以获取 id ,然后取出来直接进行字符匹配,判断是否正确。
    allenhu
        16
    allenhu  
       2017-02-15 18:28:55 +08:00
    @cloudzhou 嗯,这个问题,不知道的还一通乱答, v 站水平也是参差不齐。
    allenhu
        17
    allenhu  
       2017-02-15 18:33:18 +08:00
    @cloudzhou 你说的这个方法有点意思,但是好像并不能解决 lz 说的问题,因为一开始,你是没法知道自增 id 是多少的,你知道的只是后面那部分
    manhere
        18
    manhere  
       2017-02-15 18:34:29 +08:00
    彩虹表?
    Abirdcfly
        19
    Abirdcfly  
       2017-02-15 18:37:15 +08:00 via iPhone
    建索引,挺快的。
    ichou
        20
    ichou  
       2017-02-15 19:39:05 +08:00 via iPhone
    2000 万数据量不大啊,感觉有索引不至于慢到不能接受哦
    ichou
        21
    ichou  
       2017-02-15 19:47:51 +08:00 via iPhone
    @cloudzhou 你不觉得你多了一次写入么,哈哈
    如果要保证原子性,你还必须要加上事务,写并发一旦飙起来,扑街
    luban
        22
    luban  
       2017-02-15 19:50:43 +08:00 via iPhone
    redis 开压缩,两三 G 内存吧
    billlee
        23
    billlee  
       2017-02-15 20:30:07 +08:00
    才两千万,直接建索引足够了
    xfwduke
        24
    xfwduke  
       2017-02-15 20:42:47 +08:00
    有效数据行长度 40 bytes
    2000kw 数据 762MB
    算上 Innodb 的空洞, 各种乱七八糟的元数据, 3GB 差不多了吧
    这点数据, 写算法都多余, 建个索引

    就现在服务器的内存量, 最后整个索引估计都在 buffer pool 里面.
    别说服务器了, 桌面机都能搞定, 并发访问不大的话
    shiny
        25
    shiny  
    PRO
       2017-02-15 20:46:18 +08:00
    做索引,而且不需要整个字符串都在索引里面。
    ryd994
        26
    ryd994  
       2017-02-16 06:46:28 +08:00 via Android
    hash 不要用 hex 字符串存,用二进制字符串或者 binary 类
    ryd994
        27
    ryd994  
       2017-02-16 06:51:44 +08:00 via Android
    另外楼上有说取前几位加列的,你们真的懂数据库索引么?
    索引 n 叉树结构本来就是先比较前面的
    如果后几位的随机性比前几位好的话,取后几位做联合索引,或者用于分表,倒是有的
    换句话说,如果这种技巧有用,数据库自己早就该用了
    azh7138m
        28
    azh7138m  
       2017-02-16 10:19:44 +08:00 via Android
    彩虹表吧,之前黄易那个我算完是 7500w 条, MySQL 分下表就好了,其他优化不做查起来也是快的飞起
    jsou
        29
    jsou  
       2017-02-16 12:30:11 +08:00
    才 2000w 数据,建个索引,一个 where 条件不就出来了.
    如果这都要优化这优化那的,那这数据库软件就不能用了.
    ijustdo
        30
    ijustdo  
       2017-02-16 16:35:11 +08:00
    把这个 32 位串当做表的主键
    Septembers
        31
    Septembers  
       2017-02-16 16:53:43 +08:00
    Septembers
        32
    Septembers  
       2017-02-16 16:57:08 +08:00
    Hex String 直接 string 储存开销有点大
    可用固长 binary 储存可获得小一半的开销(同时也能降低索引的储存开销)
    see https://dev.mysql.com/doc/refman/5.7/en/binary-varbinary.html
    abccoder
        33
    abccoder  
       2017-02-16 17:06:23 +08:00
    建立索引直接搞
    ijustdo
        34
    ijustdo  
       2017-02-16 17:08:23 +08:00
    别在 yy 其它建撒索引了 把这个 32 位串当做表的主键 这样最快 不行你们可以试试看
    realpg
        35
    realpg  
    PRO
       2017-02-19 12:26:24 +08:00
    高度怀疑楼主只是在编问题,根本没有这个环境进行测试

    首先使用我的专用低性能测试机(用于测试程序性能) MYSQL 导入 2000W 条记录,插入 2000W 条数据用时 2787 秒(因为生成随机串的发生器有一定不随机性,生成了一部分重复数据,实际数据量 19787975 条,近似当两千万看吧 懒得继续插了)



    结构(索引情况)


    服务器配置:
    AMD 不知道啥时候的双核低端 CPU , 2G*2 DDR2 800 内存,硬盘 500G 普通 SATA 淘汰硬盘

    随便从库里找 50 个串进行搜索,使用 SQL NO CACHE 同时每个数据只查一次避免其他缓存干扰

    执行时间均为 0.00002 秒
    realpg
        36
    realpg  
    PRO
       2017-02-19 12:30:52 +08:00
    不小心发出去了
    插入两千万条数据用了将近 3000 秒,对我的破机器 IO 性能有直接概念了吧
    DDR2 内存时期的古董双核 AMD 入门 CPU ,执行性能也有概念了吧
    索引直接加在 hash_id 上,未限定索引长度,全默认,唯一索引

    直接检索,都是 0.0002 秒这个量级,检索过一次产生缓存以后,每次查询都是 0.0001
    mingyun
        37
    mingyun  
       2017-04-15 21:57:32 +08:00
    @realpg 赞实践
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5475 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 44ms UTC 06:35 PVG 14:35 LAX 22:35 JFK 01:35
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86