加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

纯真ip数据库查询的php实现(补充分组查询)

发布时间:2020-12-13 14:12:04 所属栏目:PHP教程 来源:网络整理
导读:原文发表于凤凰花论坛: http://www.fenghuanghua.com/bbs/viewthread.php?tid=34extra=page%3D1 有兴趣的朋友可以在那里讨论。 纯真数据库 是国内用的最多的ip-地理信息数据库,虽然不怎么专业,但是数据蛮全的,数据结构也比较合理。 关于纯真数据库的数据

原文发表于凤凰花论坛:http://www.fenghuanghua.com/bbs/viewthread.php?tid=34&extra=page%3D1 有兴趣的朋友可以在那里讨论。 纯真数据库是国内用的最多的ip-地理信息数据库,虽然不怎么专业,但是数据蛮全的,数据结构也比较合理。

关于纯真数据库的数据结构,可以看一下lumaqq的文档,里面有一点说的不太清楚,就是里面的ip和地理信息不是一对一,是多对一,所以ip一般是ip段。查询的时候是查询ip地址落在哪个段。

纯真数据库的查询算法也已经有人实现了:http://www.itlearner.com/article/2008/4055.shtml

用的是线性表的二分查询。

纯真数据库比较大,大约有60万的记录,上面的算法基本上可以接受了,平均查询效率在2ms左右,对于单机程序,完全可以忽略,但是对于并发比较大的系统,比如统计系统,这样的效率还不够。

既然数据是线性存储的,那么就可以采用分段查询,预先将数据隔成段,查询时,先找到相应的段,然后进行二分查询。

二分查询的平均查找长度是:lg(n+1)-1
那么分块询找+二分查询的平均查找长度就是:(设块数为N)分块也进行二分查找,所以查找块的平均长度是lg(N+1)-1,每块长度是n/N ,所以最终长度是:lg(N+1)-1 + lg(n/N+1)-1

根据上面的公式,代入n可以算出一个最佳块数N,也就是最佳查询时间了。数据量越大,查询速度越快,数据量比较小的表就没必要分块了。

我高数学得不好,不知道对不对。请大虾指正,另外帮忙算一下6249322条数据的最佳块数。

修改后的代码如下:(function separate($count)是我添加的分块函数,if($separator){}所在部分是二分查找块)

<?php
/**
* IP 地理位置查询类
* 增加分块查询算法
*
* @author 马秉尧
* @version 1.5
* @copyright 2005 CoolCode.CN
* @modified by david??blog:blog.iyi.cn bbs:www.fenghuanghua.com
*/
class IpLocation {
? ? /**
? ???* QQWry.Dat文件指针
? ???*
? ???* @var resource
? ???*/
? ? var $fp;

? ? /**
? ???* 第一条IP记录的偏移地址
? ???*
? ???* @var int
? ???*/
? ? var $firstip;

? ? /**
? ???* 最后一条IP记录的偏移地址
? ???*
? ???* @var int
? ???*/
? ? var $lastip;

? ? /**
? ???* IP记录的总条数(不包含版本信息记录)
? ???*
? ???* @var int
? ???*/
? ? var $totalip;

? ? /**
? ???* 返回读取的长整型数
? ???*
? ???* @access private
? ???* @return int
? ???*/
? ? function getlong() {
? ?? ???//将读取的little-endian编码的4个字节转化为长整型数
? ?? ???$result = unpack('Vlong',fread($this->fp,4));
? ?? ???return $result['long'];
? ? }

? ? /**
? ???* 返回读取的3个字节的长整型数
? ???*
? ???* @access private
? ???* @return int
? ???*/
? ? function getlong3() {
? ?? ???//将读取的little-endian编码的3个字节转化为长整型数
? ?? ???$result = unpack('Vlong',3).chr(0));
? ?? ???return $result['long'];
? ? }

? ? /**
? ???* 返回压缩后可进行比较的IP地址
? ???*
? ???* @access private
? ???* @param string $ip
? ???* @return string
? ???*/
? ? function packip($ip) {
? ?? ???// 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,
? ?? ???// 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串
? ?? ???return pack('N',intval($ip));
? ? }

? ? /**
? ???* 返回读取的字符串
? ???*
? ???* @access private
? ???* @param string $data
? ???* @return string
? ???*/
? ? function getstring($data = "") {
? ?? ???while (ord($char = fread($this->fp,1)) > 0) {? ?? ???// 字符串按照C格式保存,以

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读