2012-06-09 28 views
1

我總共有三張表,其中一張帶有玩家姓名和最後一次登錄,另一張帶有玩家姓名和IP。這些來自遊戲服務器,但是它是服務器的兩個單獨的「插件」,所以我不能將它們合併到一個表中。加入IP2C表的最快方法?

我成功地加入這兩個上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-國家或地區)表,以及,和我想同時得到這些結果。然而,這個表格非常大,如果我做了一個標準的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` 

回答

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表。

+0

該表將它們存儲爲字符串和整數。整數來自php函數ip2long(),它將字符串轉換爲長整數。然而,我不能在MySQL中找到這個函數的替代品,所以我不知道如何比較IP字符串(來自表格)和IP2C數據庫 –

+0

也許還會將長版本添加到'lb-players'表中? – Andomar

+0

我該怎麼做? lb-players表和mcmmo_users表都是通過java服務器小程序生成的,我可以嘗試編輯這些插件的源以添加長版本,但我不知道ip2long如何在Java中工作 –