Я думаю, что ответ 4 правильный. Есть несколько соображений:
тип подзапроса - коррелирован он или нет. Рассмотрим:
SELECT *
FROM t1
WHERE id IN (
SELECT id
FROM t2
)
Здесь подзапрос не связан с внешним запросом. Если число значений в t2.id мало по сравнению с t1.id, вероятно, наиболее эффективно сначала выполнить подзапрос и сохранить результат в памяти, а затем сканировать t1 или индекс на t1.id, сопоставляя его с кэшированные значения.
Но если запрос:
SELECT *
FROM t1
WHERE id IN (
SELECT id
FROM t2
WHERE t2.type = t1.type
)
здесь подзапрос коррелирован - нет способа вычислить подзапрос, если не известен t1.type. Поскольку значение для t1.type может варьироваться для каждой строки внешнего запроса, этот подзапрос может быть выполнен один раз для каждой строки внешнего запроса.
Опять же, СУБД может быть очень умной и понимать, что существует только несколько возможных значений для t2.type. В этом случае он все еще может использовать подход, используемый для некоррелированного подзапроса, если он может предположить, что стоимость выполнения подзапроса будет дешевле, чем выполнение его для каждой строки.