2012-05-04 2 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 индексируются.

Можете ли вы порекомендовать мне, как ускорить этот запрос?

// EDIT

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 '. Я подозреваю, что «LEFT JOIN», основанный на «BETWEEN», является убийцей производительности badass. – 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 на 2 спертых индекса - измените их на KEY ip_range (ip_from, ip_to).

Смежные вопросы