加入IP2C表的最快方法?

时间:2012-06-09 14:23:19

标签: php mysql sql join

我总共有三张桌子,一张有玩家名字和最后一张登录,另一张桌子有玩家名字和他们的IP。这些来自游戏服务器,但它是服务器的两个独立的“插件”,所以我不能将它们合并到一个表中。

我在playername列上成功加入了这两个:

SELECT
 u.`user` as `ign`,
 lb.`lastlogin` as `date`,
 lb.`ip`
FROM `mcmmo_users` u
 LEFT JOIN `lb-players` lb
  ON u.`user`=lb.`playername`

这些产生以下数组:Array(ign,date,ip);

但是,我也有一个IP2C(IP-Country)表,我想同时得到这些结果。但是,这个表非常大,如果我做了标准的LEFT JOIN,会大大减慢查询速度。

有更快的方式加入吗?我宁愿不查询数据的每个PHP循环。

我正在使用MySQL和PHP

IP2C数据库的布局如下:

begin_ip | end_ip | begin_ip_num | end_ip_num | country_code | country_name

并且查询如下:

$IPNUM = sprintf("%u",ip2long($ip));

SELECT `country_code` 
  FROM `cpanel_ip2c` 
 WHERE `$IPNUM` BETWEEN `begin_ip_num` AND `end_ip_num`

1 个答案:

答案 0 :(得分:2)

很难为数据库优化between条件。相反,请考虑查询大于或等于用户IP的第一个IP块:

select  *
from    mcmmo_users u
left join
        `lb-players` lb 
on      u.user = lb.playername
left join
        cpanel_ip2c ip
on      ip.begin_ip_num = 
        (
        select  begin_ip_num
        from    cpanel_ip2c ip
        where   ip.begin_ip_num <= inet_aton(lb.ip)
        order by
                ip.begin_ip_num desc
        limit   1
        )
        and inet_aton(lb.ip) <= ip.end_ip_num

使用cpanel_ip2c(begin_ip_num )上的索引,可以使用索引搜索来解析该国家/地区。

这是一个example on SQL Fiddle,为简单起见省略了mcmmo_users表。