2016-03-09 3 views
0

Учитывая этот сценарий в Oracle SQLЭффективность присоединиться к таблице или присоединиться выберите * из таблицы

select * from a join b; 

против

select * from a join (select * from b); 

против

select * from a join (select col1 from b); 

предположить в последнем сценарии есть в не менее 5 столбцов в b.

В такой ситуации было бы быстрее присоединяться напрямую или быстрее, чтобы присоединиться к выбору?

Что делать, если соединение с выбранным не выбирает все столбцы, а их крошечную часть.

P.S. пожалуйста, извините псевдокод.

+0

Не существует платформы SQL, которая не позволяет вам взглянуть на план выполнения. Вы можете просто взглянуть на план выполнения и увидеть, что первые два кросс-соединения одинаковы. Немой, чтобы выполнить крест, он будет очень медленным и редко нужен. Но то же самое. – Hogan

+0

Нельзя указывать столбцы соединения, например, если вы присоединяетесь к B в col1 и выбираете col2, и у вас есть индекс в col1, col2, тогда Oracle будет читать только индекс. Если включить все данные столбцов из таблицы B, тогда таблица должна быть прочитана, что, конечно, будет дороже. При перекрестном объединении, даже если выбранный столбец индексируется, Oracle все равно выполнит полное сканирование таблицы, так как индекс не будет включать в себя значения, которые должны быть включены в перекрестное соединение. Если у вас есть сомнения - PLAY EXPLAIN - ваш друг! –

+0

@MichaelBroughton - если нет столбцов объединения, то это кросс-соединения. Почему предположить, что пользователь не хочет перекрестных соединений? – Hogan

ответ

0

Скорее всего, ваш первый и второй варианты будут делать то же самое под капотом. Возможно, вы проиграете некоторую внутреннюю оптимизацию, выполнив метод join (select * from b).

Предполагая, что ваша таблица b содержит большой объем данных, выбор подмножества этих данных позволит оптимизировать производительность. Вероятно, это связано с тем, что вы используете select * во внешнем запросе, который, в свою очередь, будет захватывать все столбцы из соединения, если вы не ограничили это соединение. Теперь предположим, что четвертый вариант:

select a.*, b.col1 from a join b; 

Было бы интересно узнать, если выше более или менее оптимальным, чем:

select * from a join (select col1 from b); 

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

+0

Я выполнил план объяснения для обоих, и снова они идентичны. К счастью, в отличие от обычного соединения при выборе *, два запроса выполнялись в одно и то же время. – user3758659

+0

", так как он уменьшает количество данных, возвращаемых в подзапросе, поэтому по существу:« За исключением того, что Oracle не должен возвращать данные из подзапроса, если он не используется позже. –

+0

Мое использование слова «возвращено» действительно предназначено для внутреннего использования, а не для вывода данных в качестве вывода. В принципе, внутри, у него меньше данных для работы, поэтому он должен сократить циклы RAM/CPU. Опять же, это в разделе «Чистая гипотеза в этой точке», и я в какой-то степени опровергаю =) –

2

Первые два - это то же самое, если вы не имеете в виду сравнение с сложным запросом. И в этом случае

это

select * from a join (select * from b where col1 = 1); 

равна этой

select * from a join b 
where b.col1 = 1; 

Последний запрос

select * from a join (select col1 from b); 

Обычно проблема Isnt в

(select col1 from b) 

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

select * from a .... 
+0

Спасибо за быстрый ответ, я понимаю, что первые два эквивалентны, меня больше интересует, работает ли один путь быстрее, чем другой. Выполнение первого запроса Я могу добиться выбора первых 50 строк менее чем за 5 секунд, а второй запрос достигнет того же 50 строк за 60 секунд. Я не уверен, что вызывает расхождение. Особенно учитывая, что я сначала запустил 5-секундный запрос, поэтому во второй раз он должен быть кэширован. – user3758659

+0

должно быть одинаковым, но единственный способ убедиться, что используется 'EXPLAIN PLAN' –

+0

Отредактировано первым комментарием. Также план объяснения для первых 2 запросов идентичен нескольким разным именам. – user3758659

Смежные вопросы