Вложенный sql работает медленнее чем 2 отдельных

Ragnarok
На сайте с 25.06.2010
Offline
208
620

Есть примерно такой запрос, упрощённый донельзя

SELECT * FROM `table1` 
WHERE `id` IN (SELECT `data_id` FROM `table2` WHERE `something` = "45")

Отображает строки 0 - 29 ( 38 всего, Запрос занял 11.2438 сек.)

разбиваю на два отдельных и вуаля

SELECT `data_id` FROM `table2` WHERE `something` = "45"

Отображает строки 0 - 29 ( 38 всего, Запрос занял 0.0084 сек.)

(результат 1,2,3,4,5,6...38, подставляю его)

SELECT * FROM `table1` WHERE `id` IN (1,2,3,4,5,6...38)

Отображает строки 0 - 29 ( 38 всего, Запрос занял 0.0003 сек.)

Почему такая разница в скорости?

//TODO: перестать откладывать на потом
S
На сайте с 30.09.2016
Offline
469
#1

Прочитайте здесь и здесь. Типа у мускуля головка болит от таких задачек - он их не умеет оптимизировать и вместо оперативной памяти пишет временные таблицы на диск.

Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
Joker-jar
На сайте с 26.08.2010
Offline
123
#2

Как много результатов во вложенном подзапросе? По something индекс построен?

Оказываю услуги веб-программиста и администратора Linux. ICQ: 751355 | Jabber: jokerjar@jabber.ru | Skype: joker-jar
ДП
На сайте с 23.11.2009
Offline
192
#3

Были такие же проблемы, в некоторых местах с джойном стало быстрее работать, чем с вложенным селектом.

S
На сайте с 12.02.2010
Offline
101
#4

1) Запросы нужно выполнять с директивой SQL_NO_CACHE

2) Нужно включить профилирование. Скорее всего у вас нет индекса и идет full scan таблицы. При разбиении на отдельные запросы понятно, что полное сканирование не нужно, вы подсовываете константу.

edogs software
На сайте с 15.12.2005
Offline
728
#5
Ragnarok:
Есть примерно такой запрос, упрощённый донельзя
SELECT * FROM `table1` 
WHERE `id` IN (SELECT `data_id` FROM `table2` WHERE `something` = "45")

Отображает строки 0 - 29 ( 38 всего, Запрос занял 11.2438 сек.)

Не сказали бы что бы так уж "донельзя", попробуйте так


SELECT table1.* FROM `table2` left join table1 on table1.id=table2.data_id where table2.something=45 and table1.id is not null group by table2.data_id

Индексы на table1.id , table2.data_id висят? Поля одинаковые?

Ragnarok:

разбиваю на два отдельных и вуаля

Версия мускула какая?

Если ниже 5.6, то там была дурацкая бага с вложенными запросами, из-за чего оптимизировать их нормально мускул в большинстве случаев не умел. В 5.6.х (х точно не помним) багу подлечили, в 5.7 вылечили окончательно. Если точнее - в 5.6 и старше мускул приводит подобный вложенный запрос к предложенным нами лефт-джоинам в большинстве случаев.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход.
PA
На сайте с 12.02.2016
Offline
24
#6
edogs:
Не сказали бы что бы так уж "донельзя", попробуйте так

SELECT table1.*
FROM `table2` left join table1 on table1.id=table2.data_id
where table2.something=45 and table1.id is not null
group by table2.data_id

если не ошибаюсь, то запрос можно упростить:


SELECT table1.*
FROM table1 left join table2 on table1.id=table2.data_id
where table2.something=45

индексы нужны по: table1.id и table2.something

в данном случае индекс по table2.data_id не используется.

. . .
dma84
На сайте с 21.04.2009
Offline
168
#7

А почему все используют LEFT JOIN, а не INNER?


SELECT
*
FROM `table1` AS `t1`
JOIN `table2` AS `t2` ON (`t2`.`data_id` = `t1`.`id` AND `t2`.`something` = 45)
GROUP BY `t1`.`id`

Можно добавить составной индекс на `t2`.`data_id` и `t2`.`something`.

edogs software
На сайте с 15.12.2005
Offline
728
#8
ps axf:
если не ошибаюсь, то запрос можно упростить:


SELECT table1.*
FROM table1 left join table2 on table1.id=table2.data_id
where table2.something=45


индексы нужны по: table1.id и table2.something
в данном случае индекс по table2.data_id не используется.

Упростить так можно только в случае если data_id только один для каждого id, иначе у Вас будут дубли.

Индекс по table2.data_id нужен что бы объединение таблиц шло по индексам в памяти, а не через построение временных таблиц на диске.

---------- Добавлено 29.11.2016 в 21:06 ----------

dma84:
А почему все используют LEFT JOIN, а не INNER?
left join достаточен, а когда он достаточен - он быстрее.
L
На сайте с 10.02.2015
Offline
128
#9

Вообще-то

LEFT JOIN и INNER JOIN - 2 большие разницы.

Плевать какой быстрее. Нужно использовать тот, который по логике возвращает нужные данные.

В данном случае - INNER JOIN.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий