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

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

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

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

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

    对于重合的区间查找,要用区间树或者线段树才能有效保证查询效率,其他所有的做法都不靠谱, bitmap 只适用于分布均匀的小量数据,只支持一个 key 的各种容器或者数据库就更不用考虑了,最坏情况要遍历大半个索引。
    strwei
    strwei
    Jan 12, 2016
    20
    碎片化
    Orzzzz
    Orzzzz
    Jan 12, 2016
    21
    zgrep
    KentY
    KentY
    Jan 13, 2016
    22
    先说说有多大
    caocheng
    caocheng
    Jan 13, 2016
    23
    比如 postgres 数据库有 inet 类型
    xuboying
    xuboying
    OP
    Jan 14, 2016
    24
    @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   ·   Privacy   ·   Solana   ·   951 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 59ms · UTC 21:58 · PVG 05:58 · LAX 13:58 · JFK 16:58
    ♥ Do have faith in what you're doing.