最新IP数据库 存储优化 查询性能优化 每秒解析上千万
高性能IP数据库格式详解
每秒解析1000多万ip qqzeng-ip-ultimate.dat 3.0版
编码:UTF8 字节序:Little-Endian
返回规范字段(如:亚洲|中国|香港|九龙|油尖旺|新世界电讯|810200|Hong Kong|HK|114.17495|22.327115)
------------------------ 文件结构 -------------------------
// 文件头 4字节
[IP段数量]
// 前缀区 8字节(4-4) 256*8
[索引区start第几个][索引区end第几个]
// 索引区 8字节(4-3-1) ip段行数x8
[结束IP数字][地区流位置][流长度]
// 内容区 长度无限制
[地区信息][地区信息]……唯一不重复
------------------------ 文件结构 ---------------------------
优势:压缩形式将数据存储在内存中,通过减少将相同数据读取到内存的次数来减少I/O.
较高的压缩率通过使用更小的内存中空间提高查询性能。
前缀区为作为缩小查询范围,索引区和内容区长度一样,
解析出来一次性加载到数组中,查询性能提高3-5倍!
压缩:原版txt为38.5M,生成dat结构为3.68M 。
和上一版本2.0不同的是索引区去掉了[开始IP数字]4字节,节省多1-2M。
3.0版本只适用[全球版],条件为ip段区间连续且覆盖所有IPV4。
2.0版本适用[全球版][国内版][国外版]
性能:每秒解析1000多万ip
创建:qqzeng-ip 于 2018-04-08
性能测试 ( CPU i7-7700K + DDR2400 16G + win10 X64 )
查询【3.0】内存优化版 3414万ip->3.318秒 每秒1028.93309222423万次
查询【3.0】内存优化版 4439万ip->4.199秒 每秒1057.1564658252万次
查询【3.0】内存优化版 4056万ip->3.821秒 每秒1061.50222454855万次
查询【3.0】内存优化版 1781万ip->1.68秒 每秒1060.11904761905万次
查询【3.0】内存优化版 3862万ip->3.66秒 每秒1055.1912568306万次
查询【3.0】内存优化版 3479万ip->3.31秒 每秒1051.05740181269万次
查询【3.0】内存优化版 2892万ip->2.713秒 每秒1065.97862145227万次
查询【3.0】内存优化版 3484万ip->3.263秒 每秒1067.72908366534万次
查询【3.0】内存优化版 2699万ip->2.548秒 每秒1059.26216640502万次
查询【3.0】内存优化版 88万ip->0.087秒 每秒1011.49425287356万次
查询【3.0】内存优化版 161万ip->0.153秒 每秒1052.28758169935万次
查询【3.0】内存优化版 91万ip->0.088秒 每秒1034.09090909091万次
查询【3.0】内存优化版 42万ip->0.041秒 每秒1024.39024390244万次
查询【3.0】内存优化版 159万ip->0.152秒 每秒1046.05263157895万次
查询【3.0】内存优化版 88万ip->0.084秒 每秒1047.61904761905万次
查询【3.0】内存优化版 123万ip->0.118秒 每秒1042.37288135593万次
查询【3.0】内存优化版 106万ip->0.101秒 每秒1049.50495049505万次
查询【3.0】内存优化版 61万ip->0.059秒 每秒1033.89830508475万次
查询【3.0】内存优化版 177万ip->0.169秒 每秒1047.33727810651万次
查询【3.0】内存优化版 106万ip->0.101秒 每秒1049.50495049505万次
查询【3.0】普通优化版 1464万ip->3.408秒 每秒429.577464788732万次
查询【3.0】普通优化版 352万ip->0.803秒 每秒438.356164383562万次
查询【3.0】普通优化版 1357万ip->3.042秒 每秒446.088099934254万次
查询【3.0】普通优化版 184万ip->0.43秒 每秒427.906976744186万次
查询【3.0】普通优化版 752万ip->1.697秒 每秒443.134944018857万次
查询【3.0】普通优化版 1795万ip->4.032秒 每秒445.188492063492万次
查询【3.0】普通优化版 1823万ip->4.076秒 每秒447.252208047105万次
查询【3.0】普通优化版 723万ip->1.622秒 每秒445.745992601726万次
查询【3.0】普通优化版 136万ip->0.319秒 每秒426.332288401254万次
查询【3.0】普通优化版 334万ip->0.756秒 每秒441.798941798942万次
查询【3.0】普通优化版 636万ip->1.435秒 每秒443.205574912892万次
查询【3.0】普通优化版 701万ip->1.578秒 每秒444.233206590621万次
查询【3.0】普通优化版 1807万ip->4.07秒 每秒443.980343980344万次
查询【3.0】普通优化版 489万ip->1.105秒 每秒442.533936651584万次
随机生成 IP
- RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
- byte[] bytes = new byte[];
- rngCsp.GetBytes(bytes);
- uint value = ReadBigEndian32(bytes[], bytes[], bytes[], bytes[]);
开发参考 (解析dat以及查询)
- public class IPSearch3Fast
- {
- private static readonly Lazy<IPSearch3Fast> lazy = new Lazy<IPSearch3Fast>(() => new IPSearch3Fast());
- public static IPSearch3Fast Instance { get { return lazy.Value; } }
- private IPSearch3Fast()
- {
- LoadDat();
- Watch();
- }
- private string datPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"qqzeng-ip-ultimate.dat");
- private DateTime lastRead = DateTime.MinValue;
- private long[,] prefmap = new long[, ];
- private uint[] endArr;
- private string[] addrArr;
- private byte[] data;
- /// <summary>
- /// 初始化二进制 qqzeng-ip-ultimate.dat 数据
- /// </summary>
- private void LoadDat()
- {
- data = File.ReadAllBytes(datPath);
- for (int k = ; k < ; k++)
- {
- int i = k * + ;
- int prefix = k;
- long startIndex = ReadLittleEndian32(data[i], data[i + ], data[i + ], data[i + ]);
- long endIndex = ReadLittleEndian32(data[i + ], data[i + ], data[i + ], data[i + ]);
- prefmap[k, ] = startIndex; prefmap[k, ] = endIndex;
- }
- uint RecordSize = ReadLittleEndian32(data[], data[], data[], data[]);
- endArr = new uint[RecordSize];
- addrArr = new string[RecordSize];
- for (int i = ; i < RecordSize; i++)
- {
- long p = + (i * );
- uint endipnum = ReadLittleEndian32(data[p], data[ + p], data[ + p], data[ + p]);
- int offset = data[ + p] + ((data[ + p]) << ) + ((data[ + p]) << );
- int length = data[ + p];
- endArr[i] = endipnum;
- addrArr[i] = Encoding.UTF8.GetString(data, offset, length);
- }
- }
- private void Watch()
- {
- FileInfo fi = new FileInfo(datPath);
- FileSystemWatcher watcher = new FileSystemWatcher(fi.DirectoryName)
- {
- IncludeSubdirectories = false,
- NotifyFilter = NotifyFilters.LastWrite,
- Filter = "qqzeng-ip-ultimate.dat",
- };
- watcher.Changed += (s, e) =>
- {
- var lastWriteTime = File.GetLastWriteTime(datPath);
- if (lastWriteTime > lastRead)
- {
- //延时 解决 正由另一进程使用,因此该进程无法访问此文件
- Thread.Sleep();
- LoadDat();
- lastRead = lastWriteTime;
- }
- };
- watcher.EnableRaisingEvents = true;
- }
- /// <summary>
- /// ip快速查询方法
- /// </summary>
- /// <param name="ip">1.1.1.1</param>
- /// <returns></returns>
- public string Find(string ip)
- {
- long val = IpToInt(ip, out long pref);
- long low = prefmap[pref, ], high = prefmap[pref, ];
- long cur = low == high ? low : BinarySearch(low, high, val);
- return addrArr[cur];
- }
- // 二分逼近 O(logN)
- private long BinarySearch(long low, long high, long k)
- {
- long M = , mid = ;
- while (low <= high)
- {
- mid = (low + high) / ;
- uint endipnum = endArr[mid];
- if (endipnum >= k)
- {
- M = mid;
- if (mid == )
- {
- break; //防止溢出
- }
- high = mid - ;
- }
- else
- low = mid + ;
- }
- return M;
- }
- private long IpToInt(string ipString, out long prefix)
- {
- //高性能
- int end = ipString.Length;
- unsafe
- {
- fixed (char* name = ipString)
- {
- int numberBase = ;
- char ch;
- long[] parts = new long[];
- long currentValue = ;
- int dotCount = ;
- int current = ;
- for (; current < end; current++)
- {
- ch = name[current];
- currentValue = ;
- numberBase = ;
- if (ch == '')
- {
- numberBase = ;
- current++;
- if (current < end)
- {
- ch = name[current];
- if (ch == 'x' || ch == 'X')
- {
- numberBase = ;
- current++;
- }
- }
- }
- for (; current < end; current++)
- {
- ch = name[current];
- int digitValue;
- if ((numberBase == || numberBase == ) && '' <= ch && ch <= '')
- {
- digitValue = ch - '';
- }
- else if (numberBase == && '' <= ch && ch <= '')
- {
- digitValue = ch - '';
- }
- else if (numberBase == && 'a' <= ch && ch <= 'f')
- {
- digitValue = ch + - 'a';
- }
- else if (numberBase == && 'A' <= ch && ch <= 'F')
- {
- digitValue = ch + - 'A';
- }
- else
- {
- break;
- }
- currentValue = (currentValue * numberBase) + digitValue;
- }
- if (current < end && name[current] == '.')
- {
- parts[dotCount] = currentValue;
- dotCount++;
- continue;
- }
- break;
- }
- parts[dotCount] = currentValue;
- prefix = parts[];
- return (parts[] << ) | ((parts[] & 0xff) << ) | ((parts[] & 0xff) << ) | (parts[] & 0xff);
- }
- }
- //简洁的 普通
- //byte[] b = IPAddress.Parse(ip).GetAddressBytes();
- //prefix = b[0];
- // return ReadBigEndian32(b[0], b[1], b[2], b[3]);
- }
- private uint ReadBigEndian32(byte a, byte b, byte c, byte d)
- {
- return (uint)((a << ) | (b << ) | (c << ) | d);
- }
- private uint ReadLittleEndian32(byte a, byte b, byte c, byte d)
- {
- return (uint)(a | (b << ) | (c << ) | (d << ));
- }
- }
- /*
- (调用例子):
- string result = IPSearch3Fast.Instance.Find("1.2.3.4");
- --> result="亚洲|中国|香港|九龙|油尖旺|新世界电讯|810200|Hong Kong|HK|114.17495|22.327115"
- */
开发代码:https://github.com/zengzhan/qqzeng-ip
最新IP数据库 存储优化 查询性能优化 每秒解析上千万的更多相关文章
- Mysql数据库调优和性能优化的21条最佳实践
Mysql数据库调优和性能优化的21条最佳实践 1. 简介 在Web应用程序体系架构中,数据持久层(通常是一个关系数据库)是关键的核心部分,它对系统的性能有非常重要的影响.MySQL是目前使用最多的开 ...
- 一次使用 Redis 优化查询性能的实践
因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,一次使用 Redis 优化查询性能的实践 应用背景 有一个应用需要上传一组ID到 ...
- SQL SERVER 查询性能优化——分析事务与锁(五)
SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...
- mysql笔记03 查询性能优化
查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...
- SQL Server查询性能优化——堆表、碎片与索引(二)
本文是对 SQL Server查询性能优化——堆表.碎片与索引(一)的一些总结. 第一:先对 SQL Server查询性能优化——堆表.碎片与索引(一)中的例一的SET STATISTICS IO之 ...
- SQL Server查询性能优化——覆盖索引(二)
在SQL Server 查询性能优化——覆盖索引(一)中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索引等 ...
- Redis 优化查询性能
一次使用 Redis 优化查询性能的实践 应用背景 有一个应用需要上传一组ID到服务器来查询这些ID所对应的数据,数据库中存储的数据量是7千万,每次上传的ID数量一般都是几百至上千数量级别. 以前 ...
- MySQL查询性能优化(精)
MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...
- 高性能mysql 第六章查询性能优化 总结(上)查询的执行过程
6 查询性能优化 6.1为什么查询会变慢 这里说明了的查询执行周期,从客户端到服务器端,服务器端解析,优化器生成执行计划,执行(可以细分,大体过程可以通过show profile查看),从服务器端返 ...
随机推荐
- python 对模块的应用你还得练点这些
1.有如下字符串:n = "路飞学城"(编程题) - 将字符串转换成utf-8的字符编码的字节,再将转换的字节重新转换为utf-8的字符编码的字符串 - 将字符串转换成gbk的字符 ...
- django初探-创建简单的博客系统
django第一步 1. django安装 pip install django print(django.get_version()) 查看django版本 2. 创建项目 打开cmd,进入指定目录 ...
- 常用Markdown公式整理 && 页内跳转注意 && Markdown preview
目录: 常用Markdown公式及注意事项 标题 列表 链接 区块 代码块 / 引用 粗体和斜体 文字块 图片 表格 横线 页内跳转注意事项 其他重要需注意 Markdown preview 前提: ...
- 【Bootstrap】bootstrap-fileinput上传文件插件
[bootstrap-fileinput] 这是个据传最好用的bootstrap相关联的文件上传控件,支持拖曳上传,多线程上传,上传文件预览等等功能. 首先还是说一下要引入的一些文件: <lin ...
- APP专业的开发公司都有这样一套开发流程,强烈建议收藏!
下面让我们来剖析到底是如何开发App的呢? 1.App界面设计开发: 通过客户提出需求,需要头脑风暴得出合适的方案和设计理念; 确认页面风格,确定整个界面的布局.关键截面的设计.文字.及其他的设计 G ...
- 1077. Kuchiguse (20)
The Japanese language is notorious for its sentence ending particles. Personal preference of such pa ...
- Tomcat服务器的常用配置
1.如何修改端口号, tomcat启动后经常会报端口冲突, 怎么办 如果部署在Linux环境下面, 首先使用netstat -apn命令检查是否是真的端口已经被占用了 如果真的被占用,进入tomcat ...
- Beta No.2
今天遇到的困难: 组员对github极度的不适应 Android Studio版本不一致项目难以打开运行 移植云端的时候,愚蠢的把所有项目开发环境全部搬上去.本身云的内存小,性能差,我们花费了太多时间 ...
- 201621123050 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 2. 使用数据库技术改造你的系统 2.1 简述如何使用数据库技术改造你的系统.要建立什么表?截图你的表设计. 答 ...
- Bate测试报告
1 测试中找出的bug Bug类型 总数 描述 修复的bug 10 1.注册成功并没有直接跳转到登录页面: 2.学校地区无限制,数字也可以: 3.虽然相同用户名不能注册,但是只是显示,注册失败,却没有 ...