根据我的IP显示我的国家,mysql优化

时间:2010-06-17 15:36:39

标签: php ip

我从http://www.wipmania.com/en/base/下载了WIPmania的worldip表 - 该表有3个字段,大约79k行:

  • startip //示例:3363110912
  • endip //示例:3363112063
  • country // example:AR(Argentina)

所以,假设我在阿根廷,我的IP地址是:200.117.248.17

1)我使用此功能将我的ip转换为long

function ip_address_to_number($ip) {
    if(!$ip) {
        return false;
    } else {
        $ip = split('\.',$ip);
        return($ip[0]*16777216 + $ip[1]*65536 + $ip[2]*256 + $ip[3]);
    }
}

2)我通过匹配长转换后的ip来搜索正确的国家/地区代码:

$sql = 'SELECT * FROM worldip WHERE '.ip_address_to_number($_SERVER['REMOTE_ADDR']).' BETWEEN startip AND endip';

相当于: SELECT country FROM worldip WHERE 3363174417 BETWEEN startip AND endip (基准:显示行0 - 0(总计1,查询耗时0.2109秒))

现在出现真实的 问题

如果另一群阿根廷人也打开网站,他们都有这些IP地址怎么办?

  • 200.117.248.17
  • 200.117.233.10
  • 200.117.241.88
  • 200.117.159.24

因为我正在缓存所有的sql查询;而不是匹配数据库中的每个IP查询,是否更好(和正确)只是通过修改这样的函数匹配IP的2个第一部分?

function ip_address_to_number($ip) {
    if(!$ip) {
        return false;
    } else {
        $ip = split('\.',$ip);
        return($ip[0]*16777216 + $ip[1]*65536);
    }
}

(注意IP的第3和第4个拆分值已被删除)。

这样就不用查询这4个值了:

  • 3363174417
  • 3363170570
  • 3363172696
  • 3363151640

...所有我要查询的是:3363110912(这是200.117。 0.0 转换为长)。

这是对的吗?任何其他想要优化这个过程的想法?

2 个答案:

答案 0 :(得分:2)

没有

193.150.1.1 - 俄罗斯知识产权 193.150.230.1 - 瑞典知识产权

您可能会将其截断为前三个八位字节,但是......您不会有那么多缓存命中。并且很可能某些/ 24网络在两个国家之间分配。有时会发出小于/ 24的块。

答案 1 :(得分:1)

你绝对必须使用WIPmania吗?如果没有,Maxmind提供了一个开源解决方案:http://www.maxmind.com/app/geolitecountry。它的优点是它是一个二进制文件,并且有一个PHP扩展(你必须编译它并安装它)。在几个项目中使用它,查找速度非常快。你可以在这里获得PCL扩展: http://pecl.php.net/package/geoip