Я очень удивлен, что вы сообщаете в запросе без подзапросов занимает так много времени. Я ожидал бы противоположного. Вы уверены, что правильно это заметили?
MySQL способен переписывать некоторые подзапросы, подобные тому, который вы показываете, если подзапрос достаточно прост. Поэтому не должно быть разницы.
Я подозреваю, что дело, о котором вы действительно спрашиваете, связано с более сложным запросом.
При использовании подзапроса в качестве таблицы MySQL может потребоваться создать временную таблицу для хранения результата подзапроса, а затем использовать эту временную таблицу для последующих объединений или поиска или сортировки.
Временные таблицы создают накладные расходы для запроса, поскольку их необходимо сохранить. Если они маленькие, временная таблица может находиться в ОЗУ. Но если объем данных слишком велик, он скопирует таблицу на диск в каталоге, указанном в параметре конфигурации tmpdir
.
Вы также должны собрать некоторую информацию о том, как MySQL собирается запустить свой запрос:
EXPLAIN select *
from (select * from table_1) a
join (select * from table_2) b
on a.id = b.acc_id\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: b
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1
filtered: 100.00
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,id
key: PRIMARY
key_len: 8
ref: test.b.acc_id
rows: 1
filtered: 100.00
Extra: NULL
В этом простом примере, EXPLAIN отчет точно так же, как если бы мы запустили этот эквивалентный запрос:
EXPLAIN select *
from table_1 a
join table_2 b
on a.id = b.acc_id\G
По крайней мере, поскольку я проверяю это на MySQL 8.0.0-dmr. Старые версии MySQL могут не поддерживать эту оптимизацию.
Но, опять же, я подозреваю, что реальный случай, который вы тестируете, включает более сложные подзапросы.
Вы также должны убедиться, что таблицы имеют нужные индексы, чтобы позволить объединению выполнять поиск индекса для соединения. В отчете EXPLAIN вы должны увидеть второй отчет таблицы «type: ref» или «type: eq_ref».
При запросе вопросов SQL это поможет, если вы разместите фактический запрос, который дал вам 40-минутное время запроса. А также запустите SHOW CREATE TABLE
для каждой таблицы в соединении, чтобы мы могли видеть, какие индексы и ограничения у вас есть в каждой таблице.
Обновление: Я запустил тот же отчет EXPLAIN на MySQL 5.6.33, и мы можем видеть, производные таблицы, созданные из подзапросов:
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: PRIMARY
table: <derived3>
type: ref
possible_keys: <auto_key0>
key: <auto_key0>
key_len: 9
ref: a.id
rows: 2
Extra: NULL
*************************** 3. row ***************************
id: 3
select_type: DERIVED
table: table_2
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1
Extra: NULL
*************************** 4. row ***************************
id: 2
select_type: DERIVED
table: table_1
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1
Extra: NULL
Хотите знать, как вы пришли к тому факту –