Что может привести к медленному выполнению запроса при использовании подзапроса, но не при отдельном запуске? - PullRequest
0 голосов
/ 07 апреля 2009

У меня есть что-то похожее на следующее:

SELECT c.id
FROM contact AS c
WHERE c.id IN (SELECT s.contact_id 
    FROM sub_table AS s
        LEFT JOIN contact_sub AS c2 ON (s.id = c2.sub_field)
    WHERE c2.phone LIKE '535%')
ORDER BY c.name

Проблема в том, что запрос занимает очень очень очень много времени (> 2 минуты), но если я возьму подзапрос, запусту его отдельно, добавлю идентификаторы и вставлю их в основной запрос, он будет выполняться гораздо быстрее, чем 1 во-вторых, включая извлечение и взятие данных.

Я проверил объяснения, как методы, так и ключи используются соответствующим образом и одинаково. Подзапрос не возвращает более 200 идентификаторов.

Что может заставить метод подзапроса занимать намного больше времени?

Кстати, я знаю, что приведенный выше запрос может быть написан с помощью объединений, но запрос у меня не может быть - это просто упрощенная версия.

Использование MySQL 5.0.22.

Ответы [ 6 ]

3 голосов
/ 07 апреля 2009
1 голос
/ 07 апреля 2009

Что произойдет, если вы попробуете это так?

SELECT c.id
FROM contact AS c
INNER JOIN (SELECT s.contact_id 
    FROM sub_table AS s
        LEFT JOIN contact_sub AS c2 ON (s.id = c2.sub_field)
    WHERE c2.phone LIKE '535%') subq ON subq.contact_id=c.id
ORDER BY c.name

Предполагая, что результат s.contact_id уникален. Вы можете добавить отличные к подзапросу, если это не так.

Я всегда использую некоррелированные подзапросы, а не оператор IN в предложении where.

0 голосов
/ 07 апреля 2009

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

0 голосов
/ 07 апреля 2009

Разве вы не можете сделать еще одно объединение вместо подзапроса?

SELECT c.id
FROM contact AS c
JOIN sub_table AS s on c.id = s.contact_id
LEFT JOIN contact_sub AS cs ON (s.id = cs.sub_field)
WHERE cs.phone LIKE '535%'
ORDER BY c.name
0 голосов
/ 07 апреля 2009

Это коррелированный подзапрос. Он запускается один раз для каждой строки во внешнем выборе. (Я думаю. У вас есть две таблицы с одинаковым именем корреляции, я предполагаю, что это опечатка. То, что вы говорите, что это нельзя переписать как объединение, означает, что это коррелировано.)

Хорошо, я дам вам кое-что попробовать. Вы говорите, что подзапрос не коррелирован, и что вы все еще не можете присоединиться к нему. И если вы берете вывод подзапроса и лексически подставляете его для подзапроса, основной запрос выполняется намного быстрее.

Итак, попробуйте следующее: превратите подзапрос в представление: create view foo, за которым следует текст подзапроса. Затем перепишите основной запрос, чтобы избавиться от предложения «IN», и вместо этого присоединитесь к представлению.

Как время для этого?

0 голосов
/ 07 апреля 2009

Вы проверили план выполнения запроса? Обычно это покажет вам проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...