• 请不要在回答技术问题时复制粘贴 AI 生成的内容
xuboying
V2EX  ›  程序员

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

  •  
  •   xuboying · Jan 12, 2016 · 5304 views
    This topic created in 3803 days ago, the information mentioned may be changed or developed.
    数据格式如下
    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 实现)
    Supplement 1  ·  Jan 14, 2016
    24 replies    2016-01-14 23:31:29 +08:00
    sunchen
        1
    sunchen  
       Jan 12, 2016
    ip 地址转化成 32 位数字, 然后经典的 bitmap 查找
    popu111
        2
    popu111  
       Jan 12, 2016 via Android
    跑一遍存到 MySQL 里面去,然后就好多啦⊙▽⊙
    luban
        3
    luban  
       Jan 12, 2016
    @popu111 存到 mysql 也是不小的
    推荐看这个, ip 数据有 txt 和作者自己封装的格式,比较准确,多种语言客户端都有代码
    http://git.oschina.net/lionsoul/ip2region
    paw
        4
    paw  
       Jan 12, 2016
    参考 纯真 IP 库 的实现,。,
    https://github.com/gwind/ylinux/tree/master/tools/IP/QQWry
    一个 py 实现
    picasso250
        5
    picasso250  
       Jan 12, 2016
    新建一个 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  
       Jan 12, 2016
    转 32 位然后筛选吧
    xuboying
        7
    xuboying  
    OP
       Jan 12, 2016
    @0987363 @luban @paw @picasso250 @popu111 @sunchen
    感谢建议,我大概有思路了,可以造一个小的索引文件,类似 startdict 的格式
    数据库我不是很熟悉,可能最终做不出我要的效果
    congeec
        8
    congeec  
       Jan 12, 2016 via iPhone
    转 32bit 数字然后存到数据库
    实在要文本的话用 btree 建立索引吧
    最后别忘了加缓存
    congeec
        9
    congeec  
       Jan 12, 2016 via iPhone
    文本只读不写的话可以分段多进程搜索,毕竟没有数据竞争,安全
    lululau
        10
    lululau  
       Jan 12, 2016
    我怎么记得一个国内的 IP 库也就几十 MB
    xuboying
        11
    xuboying  
    OP
       Jan 12, 2016
    Livid
        12
    Livid  
    MOD
    PRO
       Jan 12, 2016
    用 Redis 的 Sorted Sets :

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

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

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