Присоединиться против подзапроса

Эта душа, которую я недавно придумал, и хотя я должен делиться ею:

select top 0
  B.*
into
  TargetTable
from
  SourceTable as A
    left join SourceTable as B on 1 = 0

Это эффективно создает дублируемую структуру SourceTable в TargetTable, при этом все столбцы обнуляются (по крайней мере, в SQL2008).

744
задан Peter Mortensen 3 November 2018 в 18:00
поделиться

5 ответов

Используйте EXPLAIN, чтобы увидеть, как ваша база данных выполняет запрос к вашим данным. В этом ответе есть огромное «это зависит» ...

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

126
ответ дан 22 November 2019 в 21:22
поделиться

Подзапросы обычно используются для возврата одной строки как атомарного значения, хотя они могут использоваться для сравнить значения с несколькими строками с ключевым словом IN. Они разрешены практически в любой значимой точке оператора SQL, включая целевой список, предложение WHERE и т. Д. В качестве условия поиска можно использовать простой подзапрос. Например, между парой таблиц:

   SELECT title FROM books WHERE author_id = (SELECT id FROM authors WHERE last_name = 'Bar' AND first_name = 'Foo');

Обратите внимание, что использование оператора обычного значения для результатов подзапроса требует, чтобы возвращалось только одно поле. Если вас интересует проверка существования одного значения в наборе других значений, используйте IN:

   SELECT title FROM books WHERE author_id IN (SELECT id FROM authors WHERE last_name ~ '^[A-E]');

Это явно отличается от, скажем, LEFT-JOIN, где вы просто хотите объединить данные из таблиц A и B даже если условие соединения не находит подходящей записи в таблице B и т. д.

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

12
ответ дан 22 November 2019 в 21:22
поделиться

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

В JOIN СУБД может создать план выполнения, который лучше подходит для вашего запроса и может предсказать, какие данные должны быть загружены для обработки, и сэкономить время, в отличие от подзапроса, в котором он будет выполнять все запрашивает и загружает все свои данные для обработки.

Преимущество подзапросов в том, что они более читабельны, чем запросы JOIN : вот почему большинство новичков в SQL предпочитают их; это легкий путь; но когда дело доходит до производительности, JOINS в большинстве случаев лучше, хотя их тоже нетрудно читать.

354
ответ дан 22 November 2019 в 21:22
поделиться

Подзапросы - это логически правильный способ решения проблем формы: «Получить факты от A при условии, что факты от B». В таких случаях логичнее вставить B в подзапрос, чем выполнять соединение. Это также более безопасно в практическом смысле, так как вам не нужно быть осторожным с получением дублированных фактов от A из-за множества совпадений с B.

На практике, однако, ответ обычно сводится к производительности. Некоторые оптимизаторы сосут лимоны, когда им предоставляется соединение с подзапросом, а некоторые - наоборот, и это зависит от оптимизатора, версии СУБД и запроса.

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

795
ответ дан 22 November 2019 в 21:22
поделиться

Прежде всего, для сравнения двух первых нужно различать запросы с подзапросами на:

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

Для первого класса запросов хорошая РСУБД будет рассматривать джойны и подзапросы как эквивалентные и будет создавать одинаковые планы запросов.

В наши дни даже mysql делает это.

Тем не менее, иногда это не так, но это не значит, что джойны всегда будут выигрывать - у меня были случаи, когда использование подзапросов в mysql улучшало производительность. (Например, если что-то мешает планировщику mysql правильно оценить стоимость и если планировщик не воспринимает join-вариант и subquery-вариант как одно и то же, то подзапросы могут превзойти joins за счет форсирования определенного пути).

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

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

41
ответ дан 22 November 2019 в 21:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: