Вопрос

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

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

против 1 индексированной строки с объединением:

    SIMPLE  s   eq_ref  PRIMARY PRIMARY 4   newsladder_production.st.submission_id  1   Using index
Это было полезно?

Решение

"Коррелированный подзапрос" (т.е. такой, в котором условие where зависит от значений, полученных из строк содержащего запроса) будет выполняться один раз для каждой строки.Некоррелированный подзапрос (тот, в котором условие where не зависит от содержащего его запроса) будет выполняться один раз в начале.Механизм SQL делает это различие автоматически.

Но, да, объясни-план расскажет тебе грязные подробности.

Другие советы

Вы запускаете подзапрос один раз для каждой строки принимая во внимание, что объединение происходит по индексам.

Вот пример того, как подзапросы вычисляются в MySQL 6.0.

Новый оптимизатор преобразует такого рода подзапросы в объединения.

Запустите поясняющий план для каждой версии, он объяснит вам, почему.

перед выполнением запросов к набору данных они проходят через оптимизатор запросов, оптимизатор пытается организовать запрос таким образом, чтобы он мог удалить как можно больше кортежей (строк) из результирующего набора как можно быстрее.Часто, когда вы используете подзапросы (особенно плохие), кортежи не могут быть удалены из результирующего набора до тех пор, пока не начнет выполняться внешний запрос.

Не видя запроса, трудно сказать, что было такого плохого в оригинале, но я предполагаю, что это было что-то, что оптимизатор просто не смог сделать намного лучше.Запустив команду "объяснить", вы увидите метод оптимизаторов для извлечения данных.

Обычно это результат того, что оптимизатор не может понять, что подзапрос может быть выполнен как объединение, и в этом случае он выполняет подзапрос для каждой записи в таблице, а затем присоединяет таблицу в подзапросе к таблице, которую вы запрашиваете.Некоторые из более "корпоративных" баз данных справляются с этим лучше, но им все равно иногда этого не хватает.

Этот вопрос носит несколько общий характер, поэтому вот общий ответ:

По сути, запросы занимают больше времени, когда в MySQL есть тонны строк для сортировки.

Сделай это:

Запустите ОБЪЯСНЕНИЕ для каждого из запросов (ОБЪЕДИНЕННОГО, затем подзапрошенного) и опубликуйте результаты здесь.

Я думаю, что увидеть разницу в интерпретации MySQL этих запросов было бы полезным опытом для всех.

Подзапрос where должен выполнить 1 запрос для каждой возвращаемой строки.Внутреннее соединение просто должно выполнить 1 запрос.

Посмотрите на план запроса для каждого запроса.

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

Оптимизатор проделал не очень хорошую работу.Обычно они могут быть преобразованы без каких-либо различий, и оптимизатор может это сделать.

Вероятно, подзапрос выполнял "полное сканирование таблицы".Другими словами, не использовать индекс и возвращать слишком много строк, которые нужно было отфильтровать Where из основного запроса.

Просто предположение, без подробностей, конечно, но это обычная ситуация.

С помощью подзапроса вы должны повторно выполнить 2-й SELECT для каждого результата, и каждое выполнение обычно возвращает 1 строку.

При объединении 2-й SELECT возвращает намного больше строк, но вам нужно выполнить его только один раз.Преимущество в том, что теперь вы можете объединяться по результатам, а объединение отношений - это то, в чем база данных должна быть хороша.Например, возможно, оптимизатор сможет определить, как теперь лучше использовать индекс.

Это не столько подзапрос, сколько предложение IN , хотя соединения лежат в основе, по крайней мере, SQL-движка Oracle и выполняются чрезвычайно быстро.

Взято из Справочного руководства (14.2.10.11 Переписывание подзапросов как объединений):

ЛЕВОЕ [ВНЕШНЕЕ] СОЕДИНЕНИЕ может быть быстрее, чем эквивалентный подзапрос, потому что сервер может быть в состоянии оптимизировать его лучше - факт, который характерен не только для сервера MySQL.

Таким образом, подзапросы могут быть медленнее, чем ЛЕВЫЕ [ВНЕШНИЕ] СОЕДИНЕНИЯ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top