Медленно ли используется соединение в предложении выбора в Oracle? - PullRequest
1 голос
/ 22 мая 2010

Я хотел бы написать запрос, подобный следующему

select 
  username, 
  (select state from addresses where addresses.username = users.username) email
from users

Это работает в Oracle (при условии, что результат внутреннего запроса уникален).Однако, есть ли снижение производительности, связанное с этим стилем написания запроса?

Ответы [ 2 ]

1 голос
/ 24 мая 2010

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

Обратите внимание, что «пользователи» - это зарезервированное слово в Oracle - вы, вероятно, хотите назвать свою таблицу как-то иначе.Также обратите внимание, что вы будете вызывать ошибки в исходной формулировке, если в адресах пользователя есть несколько записей.Обычные объединения просто вернут вам несколько строк.

Используя мои собственные таблицы с разумным индексированием и объемами данных, планы объяснения были:

Оригинал

SELECT STATEMENT  ALL_ROWSCost: 226  Bytes: 390,570  Cardinality: 39,057        
    2 TABLE ACCESS BY INDEX ROWID TABLE X83109.FN_AR_INVOICE Cost: 2  Bytes: 13  Cardinality: 1     
        1 INDEX UNIQUE SCAN INDEX (UNIQUE) X83109.I_FN_AR_INVOICE Cost: 1  Cardinality: 1  
    3 TABLE ACCESS FULL TABLE X83109.FN_AR_LINE_ITEM Cost: 226  Bytes: 390,570  Cardinality: 39,057  

Либо ANSI Join (как указано выше), либо традиционный Oracleсинтаксис, показанный ниже

select users.username as username, addresses.state as email from users, addresses where users.username = addresses.username; 

SELECT STATEMENT  ALL_ROWSCost: 377  Bytes: 898,311  Cardinality: 39,057        
    3 HASH JOIN  Cost: 377  Bytes: 898,311  Cardinality: 39,057     
        1 TABLE ACCESS FULL TABLE X83109.FN_AR_INVOICE Cost: 149  Bytes: 333,788  Cardinality: 25,676  
        2 TABLE ACCESS FULL TABLE X83109.FN_AR_LINE_ITEM Cost: 226  Bytes: 390,570  Cardinality: 39,057 

Так что нет большой разницы.Вы можете свободно использовать объединения, а также следить за производительностью.

1 голос
/ 22 мая 2010

Это не join само по себе, а конкатенация подзапроса с основным оператором select.

Чтобы это было соединение (что намного быстрее), вам потребуется следующий синтаксис:

select users.username as username, addresses.state as email from users
left join state on (users.username = addresses.username)

Использование подзапросов в операторе select всегда несет штраф в СУБД. Думайте о каждом подзапросе как об отдельной временной таблице, которая существует в памяти только на время запроса, после которого СУБД уничтожает его. Сначала он выделяет память для основной select, затем он выделяет еще больше памяти для таблицы подзапросов, выполняет подзапрос полностью, а затем просматривает обе таблицы для сопоставления набора результатов.

Кроме того, временные таблицы не имеют оптимизации индекса, поскольку они являются производной таблицей, и СУБД была запрограммирована так, чтобы не тратить время на создание индекса (если СУБД не является действительно очень умной).

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

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