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

对于一个保存了 ip 起止地址的巨型文本数据库,怎么优化才能既方便查找又节约空间?

  •  
  •   xuboying · 2016 年 1 月 12 日 · 5139 次点击
    这是一个创建于 3673 天前的主题,其中的信息可能已经有所发展或是发生改变。
    数据格式如下
    0.0.0.0,1.1.1.0, 信息 0
    1.1.1.1,2.2.2.2, 信息 1
    2.2.2.3,2.5.5.5, 信息 3
    2.5.5.6,...
    文本数据量非常大,不方便一次全读入内存,如果 grep 一个 ip 地址也可能落在区间找不到
    有什么方法可以既压缩数据,又方便查找么
    sqlite 可以么,能否支持查询 ip 区间
    (程序语言希望用 python 实现)
    第 1 条附言  ·  2016 年 1 月 14 日
    24 条回复    2016-01-14 23:31:29 +08:00
    sunchen
        1
    sunchen  
       2016 年 1 月 12 日
    ip 地址转化成 32 位数字, 然后经典的 bitmap 查找
    popu111
        2
    popu111  
       2016 年 1 月 12 日 via Android
    跑一遍存到 MySQL 里面去,然后就好多啦⊙▽⊙
    luban
        3
    luban  
       2016 年 1 月 12 日
    @popu111 存到 mysql 也是不小的
    推荐看这个, ip 数据有 txt 和作者自己封装的格式,比较准确,多种语言客户端都有代码
    http://git.oschina.net/lionsoul/ip2region
    paw
        4
    paw  
       2016 年 1 月 12 日
    参考 纯真 IP 库 的实现,。,
    https://github.com/gwind/ylinux/tree/master/tools/IP/QQWry
    一个 py 实现
    picasso250
        5
    picasso250  
       2016 年 1 月 12 日
    新建一个 table ipt
    有 3 列,如下:
    ip_start int
    ip_end int
    info varchar

    在 ip_start 和 ip_end 上各建一个索引

    将这个 txt 跑一遍,存下来

    select * from ipt where ip_start <= ? and ip_end >= ?
    0987363
        6
    0987363  
       2016 年 1 月 12 日
    转 32 位然后筛选吧
    xuboying
        7
    xuboying  
    OP
       2016 年 1 月 12 日
    @0987363 @luban @paw @picasso250 @popu111 @sunchen
    感谢建议,我大概有思路了,可以造一个小的索引文件,类似 startdict 的格式
    数据库我不是很熟悉,可能最终做不出我要的效果
    congeec
        8
    congeec  
       2016 年 1 月 12 日 via iPhone
    转 32bit 数字然后存到数据库
    实在要文本的话用 btree 建立索引吧
    最后别忘了加缓存
    congeec
        9
    congeec  
       2016 年 1 月 12 日 via iPhone
    文本只读不写的话可以分段多进程搜索,毕竟没有数据竞争,安全
    lululau
        10
    lululau  
       2016 年 1 月 12 日
    我怎么记得一个国内的 IP 库也就几十 MB
    xuboying
        11
    xuboying  
    OP
       2016 年 1 月 12 日
    Livid
        12
    Livid  
    MOD
    PRO
       2016 年 1 月 12 日
    用 Redis 的 Sorted Sets :

    http://redis.io/commands#sorted_set
    TaMud
        13
    TaMud  
       2016 年 1 月 12 日
    ip 数据库都能卖钱〜〜〜〜〜
    ryd994
        14
    ryd994  
       2016 年 1 月 12 日
    用 CIDR ,查询的时候按 prefix 长度顺序查
    mlhadoop
        15
    mlhadoop  
       2016 年 1 月 12 日
    字典树可以吗?
    wbsdty331
        16
    wbsdty331  
       2016 年 1 月 12 日
    纯真 IP 看 i
    skydiver
        17
    skydiver  
       2016 年 1 月 12 日
    有多巨型?
    raysonx
        18
    raysonx  
       2016 年 1 月 12 日 via Android
    IP 地址轉為 32 位二進制存儲,建立索引使用二分查找
    h4x3rotab
        19
    h4x3rotab  
       2016 年 1 月 12 日 via iPhone   ❤️ 1
    数据和 key 分离是必须的,你肯定要一个索引。

    首先 ipv4 地址就是一个 int32 ,所以 key 很好处理。其次要看你的区间会不会重叠,没有交集自然随便搞,是排序之后二分查找,还是丢进什么可以查找的树结构都没问题。但是如果区间会重合,上面大多数人的答案都是错的。

    对于重合的区间查找,要用区间树或者线段树才能有效保证查询效率,其他所有的做法都不靠谱, bitmap 只适用于分布均匀的小量数据,只支持一个 key 的各种容器或者数据库就更不用考虑了,最坏情况要遍历大半个索引。
    strwei
        20
    strwei  
       2016 年 1 月 12 日
    碎片化
    Orzzzz
        21
    Orzzzz  
       2016 年 1 月 12 日
    zgrep
    KentY
        22
    KentY  
       2016 年 1 月 13 日
    先说说有多大
    caocheng
        23
    caocheng  
       2016 年 1 月 13 日
    比如 postgres 数据库有 inet 类型
    xuboying
        24
    xuboying  
    OP
       2016 年 1 月 14 日
    @0987363 @KentY @Livid @Orzzzz @TaMud @caocheng @congeec @h4x3rotab @luban @strwei @raysonx
    感谢各位帮忙献计献策,我最终用了 stardict 的格式的解决方案,为 csv 数据建立索引,再用二分查找法搜索,数据库不熟悉,没有采用,具体见 https://code.csdn.net/snippets/1556752
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   854 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:28 · PVG 05:28 · LAX 13:28 · JFK 16:28
    ♥ Do have faith in what you're doing.