我目前正在为其他人转换脚本,在他们的旧代码中,他们有一个CSV文件列出所有IP及其国家/地区。该文件采用以下格式:
16777216 17367039 AU AUS AUSTRALIA
17367040 17432575 MY MYS MALAYSIA
17432576 17498111 AU AUS AUSTRALIA
17498112 17563647 KR KOR REPUBLIC OF KOREA
17563648 17825791 CN CHN CHINA
很好,就是他们所做的,我把它导入了新的MySQL DB。但问题是他们在这里有111K记录!
要进行比较并找到国家/地区的IP,大约需要40秒。目前,他们选择所有记录并与低于和超过下一个字段进行比较。
$datafile = file("iplist.csv");
$countries = array();
foreach($datafile as $data) {
$data = explode(",", $data);
foreach($iplist as $ipan => $ip) {
if($ip > $data[0] && $ip < $data[1]) {
$countries[$ip] = array($data[2], $data[4]);
}
}
}
当然我知道这是一个可怕的方法来做到这一点,太可怕了!当我在MySQL中这样做时甚至很糟糕,我的意思是111K记录只是坐在那里。
我整天都在绞尽脑汁,无论如何都无法想到这样做。 IP以标准格式存储在DB中。我以为我只是从MySQL中做一个选择,而在where语句中做了多于和少于。但对于我的生活,我可以想到如何。考虑到这是他们如何制作他们的IP列表:
foreach($log as $row) {
$iplist[$row[2]] = $row[2];
if($last != "") {
$dif = $last-$row[5];
$avgtime += $dif;
}
$last = $row[5];
}
我想过为每条记录做一次调用,但是如果每个统计页面上有120条记录正常,那么那就是因为那将是120次调用mysql最小值。
有人能给我一个更好,更有效的方法来进行比较吗?
我在考虑使用外部服务,但请求会非常多,我认为该网站会被列入黑名单。
答案 0 :(得分:0)
为什么不试试这个:
SELECT * FROM table WHERE ip_min >= $your_value and ip_max <= $your_value
ip_min
将是第一列数据,ip_max
是第二列。 $your_value
显然是你知道的ip值。
同样关于geoIP位置,为什么不寻找像MaxMind这样的标准数据库之一。我个人喜欢使用带有MaxMind数据库的mod_geoip
模块在Web服务器上处理country ip geoLocation。然后,您可以每月更新此数据库,而不必担心尝试在应用程序中保留当前的IP数据库。 mod_geoip
只是向$_SERVER
超全球公开了一些额外的价值,您可以阅读这些价值以获取国家/地区代码或国家/地区名称(甚至是城市名称)。
答案 1 :(得分:0)
您应该在mysql查询中使用join:
SELECT s.*, g.country_code, g.country_name FROM stats s LEFT JOIN geoip g ON ( g.ip_min <= s.ip AND g.ip_max >= s.ip )
然后你将在一个查询中拥有它。
使用INNER JOIN
代替LEFT JOIN
更快,但不会选择ip超出范围的记录
无论如何,我认为在插入统计数据表之前找到该位置并分配具有统计记录的国家/地区的ID会好得多 - 您还必须加入它,但它会更快地运行