简体   繁体   English

PHP / MySQL IP到“国家/地区”统计页面

[英]PHP/MySQL IP to country for Stats page

I am currently converting a script for someone else and in their old code they had a CSV file listing all IPs and their countries. 我目前正在为其他人转换脚本,在他们的旧代码中,他们有一个CSV文件,其中列出了所有IP及其所在的国家/地区。 The file was in this format: 该文件的格式如下:

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

Fine, that's what they did, I imported it to the new MySQL DB. 很好,这就是他们所做的,我将其导入了新的MySQL数据库。 But problem is they have 111K records here! 但是问题是他们这里有111K记录!

To do the comparison and find IP to country it takes around 40 seconds. 要进行比较并找到国家/地区的IP,大约需要40秒。 Currently they select all records and compare to less than and more than the next field. 当前,他们选择所有记录并与下一个字段进行比较。

$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]);
            }
        }
    }

Of course I know this is a HORRIBLE way to do this, horrible! 我当然知道这是一种可怕的方式,太可怕了! It's even bad when I do it in MySQL, I mean 111K records just sitting there. 当我在MySQL中执行操作时,这甚至很糟糕,我的意思是就坐在那里的111K条记录。

I've been wracking my brain all day and can't think of anyway better to do this. 我整天都在动脑筋,再也想不到这样做了。 IPs are stored in the DB in standard format. IP以标准格式存储在DB中。 I thought I would just do a select from MySQL and in the where statement do a more than and less than. 我以为我只会从MySQL中进行选择,而在where语句中则执行大于和小于。 But for the life of me I can think of how. 但是对于我的一生,我可以想到。 Considering this is how they make their IP list: 考虑到这是他们制作IP列表的方式:

foreach($log as $row) {
        $iplist[$row[2]] = $row[2];

        if($last != "") {
            $dif = $last-$row[5];
            $avgtime += $dif;
        }
        $last = $row[5];
    }

I thought of doing one call per record, but if there are a normal of 120 records that come out on each stat page then that's out since that would be 120 calls to mysql minimum. 我想对每条记录进行一次调用,但是如果每个统计页上正常出现120条记录,那么该记录就消失了,因为那将是对mysql的最少120次调用。

Can anyone give me a better and more efficient way to get this comparison? 谁能给我一种更好,更有效的方式进行比较?

I was thinking of using an outside service, but the requests would be so much I think the site would get blacklisted. 我当时在考虑使用外部服务,但是请求太多了,我认为该站点将被列入黑名单。

WHy not try this: 为什么不试试这个:

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

Where ip_min would be that first column of data and ip_max is the 2nd column. 其中ip_min是数据的第一列,而ip_max是第二列。 $your_value would obviously be the ip value that is known to you. $your_value显然是您所知道的ip值。

Also with regards to geoIP location, why not look to one of the standard databases like MaxMind. 此外,关于geoIP位置,为什么不使用MaxMind这样的标准数据库之一。 I personally like to handle the country ip geoLocation on the web server using the mod_geoip module with MaxMind database. 我个人喜欢使用带有MaxMind数据库的mod_geoip模块在Web服务器上处理国家/地区ip geoLocation。 You can then just update this database on a monthly basis and not have to worry about trying to keep a current IP Database in your application. 然后,您可以每月更新一次此数据库,而不必担心尝试在应用程序中保留最新的IP数据库。 mod_geoip simply exposes a few additional value into the $_SERVER superglobal that you can read to get country code or country name (or even down to city). mod_geoip只是向$_SERVER超全局变量公开了一些其他值,您可以读取这些值以获得国家/地区代码或国家/地区名称(甚至是城市名称)。

You should use join in your mysql query: 您应该在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 ) 

Then you'll have it in one query. 然后,您将在一个查询中拥有它。

Faster would be use INNER JOIN instead of LEFT JOIN but then it won't select record with ip out of range 使用INNER JOIN而不是LEFT JOIN更快,但是它不会选择ip超出范围的记录

Anyway I think it would be much better to find that location before inserting to stats table and assign ID of country with stats record - you'll also have to join it, but it will work much faster 无论如何,我认为最好先找到该位置,然后再插入统计信息表,并为国家/地区ID分配统计信息记录-您也必须加入它,但它的工作速度更快

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM