2015-11-30 5 views
0

У меня есть таблица изменений обхода дерева подстроки (MPTT) с 82117 записями. Эта таблица MySQL содержит некоторые географические данные (Страна, Штат, регион, город ...)Как оптимизировать медленный Модифицированный запрос обхода дерева подзаголовка

CREATE TABLE IF NOT EXISTS `geotree` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `geo_id` int(11) DEFAULT NULL, 
    `name` varchar(80) COLLATE utf8_unicode_ci NOT NULL, 
    `lft` int(11) NOT NULL, 
    `rgt` int(11) NOT NULL, 
    `parent` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `name` (`name`,`lft`,`rgt`), 
    KEY `geo_id` (`geo_id`), 
    KEY `parent` (`parent`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=82174 ; 

Проблема возникает, когда я пытаюсь получить путь, используя стандартный MPTT запрос следующим образом:

SELECT p.name 
FROM `geotree` AS node, `geotree` AS p 
WHERE node.lft BETWEEN p.lft AND p.rgt AND node.rgt='$value' 
ORDER BY p.lft 

Требуется больше 2,5 секунд. В чем проблема? Я пропустил какой-либо индекс? Слишком много строк для такого типа структуры данных? Или есть ошибка в запросе?

ПРИМЕЧАНИЕ. Я заметил, что если я удалю «ORDER BY» из запроса, время запроса уменьшится до 0,05 секунд.

+0

К сожалению, в MySQL join не может использовать индексы для условий диапазона ('BETWEEN',' <','> ', ...). В этом случае время выполнения становится пропорциональным <количеству строк в таблице> * <количество строк с rgt = значение>. – Vatev

ответ

0

Вы должны, по крайней мере, превратить ваш запрос к надлежащему JOIN, который должен принести некоторое представление:

http://sqlfiddle.com/#!9/b4d7f8/3

SELECT p.name 
FROM `geotree` AS node 
INNER JOIN `geotree` AS p 
ON node.lft BETWEEN p.lft AND p.rgt 
WHERE node.rgt='$value' 

И так как вам нужно node.rgt='$value' как фильтр я бы добавить индекс KEY rgt (rgt)

+0

Для этого запроса я должен добавить «ORDER BY p.lft», чтобы получить правильный порядок. Как только я это сделаю, это займет 2,4 секунды, немного быстрее, но не достаточно. То же самое после добавления «KEY rgt (rgt)» занимает 0.25 секунды, что очень близко к ожидаемой производительности, но все же недостаточно (+1 для этого!). – Ivan

+0

Это точно так же, как исходный запрос OP. Почему вы думаете, что у него будет другая производительность? – Vatev