0

我目前正在为其他人转换一个脚本,在他们的旧代码中,他们有一个 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 数据库中。但问题是他们这里有 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 以标准格式存储在数据库中。我以为我会从 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 调用。

谁能给我一个更好,更有效的方法来进行这种比较?

我正在考虑使用外部服务,但请求太多了,我认为该网站会被列入黑名单。

4

2 回答 2

0

为什么不试试这个:

SELECT * FROM table WHERE ip_min >= $your_value and ip_max <= $your_value

ip_min第一列数据在哪里,第二列在哪里ip_max$your_value显然是您已知的 ip 值。

另外关于 geoIP 位置,为什么不看看 MaxMind 等标准数据库之一。我个人喜欢使用mod_geoip带有 MaxMind 数据库的模块来处理 web 服务器上的国家/地区 ip geoLocation。然后,您可以每月更新此数据库,而不必担心尝试在您的应用程序中保留当前的 ​​IP 数据库。 mod_geoip只需将一些额外的价值暴露给$_SERVER你可以阅读的超全球,以获取国家代码或国家名称(甚至是城市)。

于 2012-10-03T22:38:02.010 回答
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 会更好 - 你还必须加入它,但它会工作得更快

于 2012-10-03T23:03:28.213 回答