1

我总共有三张表,一张是玩家姓名和他们的最后一次登录,另一张是玩家姓名和他们的 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`
4

1 回答 1

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 ),可以通过索引查找来解决国家/地区问题。

这是一个关于 SQL Fiddle 的示例mcmmo_users,为简单起见省略了该表。

于 2012-06-09T15:23:32.780 回答