Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Долго выполняется двухуровневый запрос


Автор: neokortex 25.11.2010, 04:53
Очень долго выполняется такой запрос
Код

SELECT *
FROM `products`
WHERE `dir`
IN (

SELECT MIN( `dir` ) AS `mindir`
FROM `products`
WHERE `text` LIKE '%текст%'
)
AND `text` LIKE '%текст%';

phpMyAdmin показывает 3,5 секунды
В чем может быть дело?

Автор: neokortex 25.11.2010, 05:20
нашел в чем проблема. надо =, а не IN
Код

SELECT *
FROM `products`
WHERE `dir`
= (
SELECT MIN( `dir` ) AS `mindir`
FROM `products`
WHERE `text` LIKE '%текст%'
)
AND `text` LIKE '%текст%';

теперь 0.0015 сек.
Обалдеть какая разница во времени. Это почему так, никто не подскажет?

Автор: Akina 25.11.2010, 08:35
См. explain запросов.

Добавлено через 1 минуту и 34 секунды
А заодно и
Код

SELECT *
FROM `products`
WHERE `text` LIKE '%текст%'
ORDER BY `dir` ASC
LIMIT 1;


Автор: A5uKa 25.11.2010, 08:52
Цитата(Akina @ 25.11.2010,  08:35)
Добавлено @ 08:37
А заодно и
Код

SELECT *
FROM `products`
WHERE `text` LIKE '%текст%'
ORDER BY `dir` ASC
LIMIT 1;

Разве так оно не выберет только одну запись ?

Автор: Akina 25.11.2010, 09:02
Цитата(A5uKa @  25.11.2010,  09:52 Найти цитируемый пост)
Разве так оно не выберет только одну запись ? 

выберет одну... с минимальным dir... Да, если dir неуникально - это (может быть) не то, что хочет ТС.

Автор: A5uKa 25.11.2010, 09:06
Код

SELECT Min ('dir') , и остальные поля
FROM `products`
WHERE `text` LIKE '%текст%';

а как такое будет работать ?

Автор: Akina 25.11.2010, 09:43
Цитата(A5uKa @  25.11.2010,  10:06 Найти цитируемый пост)
а как такое будет работать ? 

Отфонарно. Остальные поля будут браться из любых записей (с dir=Min(dir), и то если звёзды сложатся).

Автор: A5uKa 25.11.2010, 09:54
Код

SELECT Min ('p1.dir') , p2.остальные поля
FROM `products` AS p1,  `products` AS p2, 
WHERE p2.`text` LIKE '%текст%' AND p1.dir=p2.dir;

то есть только так ?

Автор: baldina 25.11.2010, 10:03
Цитата(A5uKa @  25.11.2010,  09:06 Найти цитируемый пост)
а как такое будет работать ? 

GROUP BY надо, и будет

Автор: Zloxa 25.11.2010, 10:53
Цитата(A5uKa @  25.11.2010,  09:54 Найти цитируемый пост)
то есть только так ? 

это ничего не меняет. Джойн выполнится раньше аггрегации и "Остальные поля" будут отобраны так же - первые попавшиеся
если уходить от in к джойну, то както так:
Код

select `p2`.*
from  (select `p1`.`dir`
        from `products` as `p1`
        where p2.`text` like '%текст%'
        order by `p1`.`dir`
        limit 1
      ) as `s`
      ,`products` AS `p2` 
WHERE p1.dir=p2.dir and p2.`text` like '%текст%';

Здесь, в принципе, пофиг, использовать лимит или min, критерии отбора не позволят использоывать индекс.
Если бы можно было использовать индекс, limit, думаю/*уверен на 80%*/, был бы предпочтительнее min

Явных преимуществ использования джойн в место in - я не вижу. Иногда стоит попробовать, когда in дает не желательный план, может статься план с джойном будет более удовлетворителен - т.е. юзабилити такого подхода мне видится лишь в целях обмана оптимизатора.

В довесок размышления в слух:
Для реализации операции in может быть выполнен semi-join, алгоритм его реализации для конкретной платформы может отличаться от от алгоритма inner-join, что может дать преимущество тому или иному подходу. Однако, на практике, сколько я ни пытался получить разницу времени отклика превосходящую погрешность измерения при сопоставимых стоимостях планов - мне не удавалось.

Автор: A5uKa 25.11.2010, 10:57
Цитата(baldina @ 25.11.2010,  10:03)
Цитата(A5uKa @  25.11.2010,  09:06 Найти цитируемый пост)
а как такое будет работать ? 

GROUP BY надо, и будет

Ок )

Автор: Zloxa 25.11.2010, 10:58
Цитата(neokortex @  25.11.2010,  05:20 Найти цитируемый пост)
Это почему так, никто не подскажет? 

как верно уже заметил Akina, попытка что либо предполагать без изучения планов обоих запросов - абсурдна.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)