2012-05-04 34 views
0

我想優化sql查詢,現在需要大約20秒來執行。優化sql查詢

這是我的表的結構。

last_login 

id | ip_address |when 
1 2130706433 2012-05-04 12:00:36 

country_by_ip 

ip_from | ip_to | country 
16843008 | 16843263 | CN 

這裏是我使用查詢:

SELECT 
ll.ip_address, 
ll.when, 
cbi.country 
FROM last_login ll 
LEFT JOIN `country_by_ip` cbi on ll.ip_address BETWEEN cbi.ip_from AND cbi.ip_to 

字段ip_from和ip_to進行索引。

你能推薦我如何加快這個查詢嗎?

//編輯

CREATE TABLE `last_login` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `ip_address` int(11) unsigned NOT NULL, 
    `when` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 


CREATE TABLE `country_by_ip` (
    `ip_from` int(20) unsigned NOT NULL, 
    `ip_to` int(20) DEFAULT NULL, 
    `country` varchar(255) DEFAULT NULL, 
    KEY `ip_from` (`ip_from`), 
    KEY `ip_to` (`ip_to`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

EXPLAIN EXTENDED

+0

請向我們展示由'SHOW CREATE TABLE last_login'和'SHOW CREATE TABLE country_by_ip'給出的表結構。另外,查看'EXPLAIN EXTENDED '給出的內容會很有用。我懷疑基於BETWEEN條款的'LEFT JOIN'是一個壞蛋表現殺手。 – Romain

+0

這些表格有多大(以行數計)? 「country_by_ip」上的聚集索引是什麼? –

+0

@romain,請參閱最新的問題。 – din2

回答

1

如何:

SELECT 
ll.ip_address, 
ll.when, 
cbi.country 
FROM last_login ll 
LEFT JOIN `country_by_ip` cbi on ll.ip_address > cbi.ip_from 
WHERE ll.ip_address < cbi.ip_to 

不過,我完全同意@Romain同意,更改數據庫架構,以更好的設計。

+0

謝謝! 查詢不僅僅花費了544ms – din2

+1

像這樣的where子句基本上使得你的連接成爲內連接。這相當於使用普通'join'而不是'left join'的原始查詢。 –

0

通過將country_by_ip範圍分成兩個sperate索引,您不會做任何好處 - 將其更改爲KEY ip_rangeip_from,ip_to)。