Что эффективно? запрос с подзапросом или объединенной таблицей - PullRequest
4 голосов
/ 06 февраля 2012

Вот два примера запроса для той же цели (в этом примере я хочу найти продавца из того же города, где живет Патрикс.)

select * 
from salesman 
where salesman.city = 
     ( select city 
       from salesman 
       where salesman_name='Patriks'
     );

и

select s1.* 
from salesman s1,salesman s2 
where s1.city=s2.city 
  and s2.salesman_name='Patriks';

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

Ответы [ 4 ]

5 голосов
/ 06 февраля 2012

Общее правило:

Если вы используете подзапрос, вы заставляете Oracle использовать определенный путь выполнения (т. Е. Он должен выполнить подзапрос, прежде чем сможет выполнить внешний запрос)

Если вы используете объединение, Oracle может свободно выбирать тот путь, который он считает наиболее эффективным.

Поэтому я бы всегда использовал объединение поверх подзапроса.YMMV.

5 голосов
/ 06 февраля 2012

Мой опыт показывает, что в Oracle плоский запрос (т. Е. Тот, у которого есть объединение) часто более эффективен, чем эквивалентный запрос, использующий вложенный выбор. Похоже, что в более сложных случаях существуют запросы, которые оптимизатор Oracle не находит, для запроса с подвыбором.

В SQL Server, DB2, Ingres и Sybase мой опыт показывает, что это не имеет значения - в этих СУБД есть оптимизаторы, которые будут находить одинаковые пути запросов независимо от того, используете ли вы плоский запрос или запрос с подвыбором.

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

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

2 голосов
/ 08 февраля 2012

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

cagcowboy неверный ответ.Oracle перепишет ваш запрос, чтобы предоставить лучший план выполнения.Запросы, подобные тому, который вы описываете, часто преобразуются в подзапрос, отменяющий .Я предполагаю, что в 9 случаях из 10 запросы, аналогичные тем, которые вы описываете, будут иметь один и тот же план выполнения.

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

Как указывает Бранко Димитриевич, два запроса, которые вы считаете одинаковыми, часто не эквивалентны.В ваших двух примерах, если salesman_name не является уникальным, ваш первый запрос выдаст исключение ORA-01427: single-row subquery returns more than one row, но ваш второй пример будет работать нормально.

2 голосов
/ 08 февраля 2012

В моем опыте, если подзапрос и JOIN означают одно и то же , Oracle выполнит их одинаково быстро.

Люди часто переписывают свои запросы и думают, что они остались эквивалентными, хотя на самом деле они вводили тонкие различия. Например, означает, что запросы OP означают одно и то же, зависит от того, является ли salesman_name ПЕРВИЧНЫМ КЛЮЧОМ (или УНИКАЛЬНЫМ). Если это не так, эти запросы больше не означают одно и то же.

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

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