Я рефакторил медленный раздел приложения, которое мы унаследовали от другой компании, чтобы использовать внутреннее соединение вместо подзапроса, такого как:
WHERE id IN (SELECT id FROM ...)
Реорганизованный запрос выполняется примерно в 100 раз быстрее. (~ 50 секунд до ~ 0,3) Я ожидал улучшения, но кто-нибудь может объяснить, почему это так радикально? Все столбцы, использованные в предложении where, были проиндексированы. SQL выполняет запрос в предложении where один раз для строки или чего-то еще?
Обновление - Объясните результаты:
Разница заключается во второй части запроса "where id in ()" -
2 DEPENDENT SUBQUERY submission_tags ref st_tag_id st_tag_id 4 const 2966 Using where
vs 1 проиндексированная строка с объединением:
SIMPLE s eq_ref PRIMARY PRIMARY 4 newsladder_production.st.submission_id 1 Using index
sql
mysql
performance
database-design
join
palmsey
источник
источник
Ответы:
«Коррелированный подзапрос» (т. Е. Тот, в котором условие where зависит от значений, полученных из строк содержащего запроса) будет выполняться один раз для каждой строки. Некоррелированный подзапрос (в котором условие where не зависит от содержащего запроса) будет выполнен один раз в начале. Механизм SQL делает это различие автоматически.
Но, да, план объяснения даст вам грязные детали.
источник
DEPENDENT SUBQUERY
означает то же самое, что и «коррелированный подзапрос».Вы выполняете подзапрос один раз для каждой строки, тогда как объединение происходит по индексам.
источник
EXPLAIN
говоритDEPENDENT SUBQUERY
, что является наиболее ярким показателем такого поведения.Вот пример того, как подзапросы оцениваются в MySQL 6.0 .
Новый оптимизатор преобразует этот вид подзапросов в объединения.
источник
Запустите объяснительный план для каждой версии, он скажет вам, почему.
источник
перед выполнением запросов к набору данных, которые они передают через оптимизатор запросов, оптимизатор пытается организовать запрос таким образом, чтобы он мог удалить как можно больше кортежей (строк) из набора результатов. Часто, когда вы используете подзапросы (особенно плохие), кортежи не могут быть удалены из результирующего набора, пока внешний запрос не начнет выполняться.
Без просмотра запроса трудно сказать, что было плохого в оригинале, но я думаю, что это было то, что оптимизатор просто не мог сделать намного лучше. Запуск объяснения покажет вам метод оптимизаторов для получения данных.
источник
Посмотрите на план запроса для каждого запроса.
Где in и Join, как правило, могут быть реализованы с использованием одного и того же плана выполнения, поэтому, как правило, скорость переключения между ними равна нулю.
источник
Оптимизатор не очень хорошо поработал. Обычно они могут быть преобразованы без какой-либо разницы, и оптимизатор может сделать это.
источник
Обычно это результат того, что оптимизатор не может выяснить, что подзапрос может быть выполнен как объединение, и в этом случае он выполняет подзапрос для каждой записи в таблице, а не соединяет таблицу в подзапросе с запрашиваемой таблицей. Некоторые из более «предприимчивых» баз данных лучше справляются с этим, но они все еще иногда упускают это.
источник
Этот вопрос несколько общий, поэтому вот общий ответ:
По сути, запросы занимают больше времени, когда в MySQL есть тонны строк для сортировки.
Сделай это:
Запустите EXPLAIN для каждого из запросов (один из них - JOIN, а затем - для Subqueried) и опубликуйте результаты здесь.
Я думаю, что увидеть разницу в интерпретации этих запросов MySQL будет полезным для всех.
источник
Подзапрос where должен выполнить 1 запрос для каждой возвращаемой строки. Внутреннее объединение просто должно выполнить 1 запрос.
источник
Подзапрос, вероятно, выполнял «полное сканирование таблицы». Другими словами, не используя индекс и возвращая слишком много строк, которые нужно было отфильтровать из основного запроса Where.
Просто предположение без подробностей, конечно, но это обычная ситуация.
источник
С подзапросом вы должны повторно выполнить 2-й SELECT для каждого результата, и каждое выполнение обычно возвращает 1 строку.
С объединением, 2-й SELECT возвращает намного больше строк, но вы должны выполнить его только один раз. Преимущество состоит в том, что теперь вы можете присоединиться к результатам, а объединение отношений - это то, что база данных должна быть хороша. Например, возможно, оптимизатор может определить, как лучше использовать индекс сейчас.
источник
Это не столько подзапрос, сколько предложение IN, хотя объединения лежат в основе по крайней мере механизма SQL Oracle и работают очень быстро.
источник
Взято из Справочного руководства ( 14.2.10.11 Перезапись подзапросов как объединений ):
Таким образом, подзапросы могут быть медленнее, чем LEFT [OUTER] JOINS.
источник