Подтвердить что ты не робот

Могу ли я повысить производительность, используя JOIN или используя EXISTS?

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

Могу ли я повысить производительность, используя JOIN или используя EXISTS?

Спасибо,
-Nimesh

4b9b3361

Ответ 1

В зависимости от оператора, статистики и сервера БД это может не иметь значения - может быть создан тот же оптимизированный план запроса.

В основном три способа объединения DB файлов под капотом:

  • Вложенный цикл - для одной таблицы намного больше второй. Каждая строка в меньшей таблице проверяется для каждой строки в большей.

  • Объединить - для двух таблиц в том же порядке сортировки. Оба выполняются по порядку и сопоставляются там, где они соответствуют.

  • Хеш - все остальное. Временные таблицы используются для создания совпадений.

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

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

Например, если [Учреждения] и [Результаты] имеют одинаковые размеры, и оба кластеризованы в InstitutionID, объединение слияния будет самым быстрым. Если [Results] намного больше [Institutions], вложенный цикл может быть быстрее.

Ответ 2

Это зависит.

В конечном счете 2 служат совершенно другим целям.

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

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

Отправьте пример двух методов, которые вы имеете в виду, и я мог бы дать вам лучшую идею.


С вашими двумя таблицами Institutions and Results, если вам нужен список учреждений, которые имеют результаты, этот запрос будет наиболее эффективным:

select Institutions.institution_name 
from Institutions
inner join Results on (Institutions.institution_id = Results.institution_id)

Если у вас есть unit_id и просто хотите узнать, есть ли у него результаты, использование EXISTS может быть быстрее:

if exists(select 1 from Results where institution_id = 2)
  print "institution_id 2 has results"
else
  print "institution_id 2 does not have results"

Ответ 3

Это зависит от вашего оптимизатора. Я попробовал следующие два в Oracle 10g и 11g. В 10 г второй был немного быстрее. В 11g они были идентичны.

Однако, # 1 действительно является неправильным использованием предложения EXISTS. Используйте сочетания для поиска совпадений.

select *
from
  table_one t1
where exists (
             select *
             from table_two t2
             where t2.id_field = t1.id_field
             )
order by t1.id_field desc


select t1.*
from 
  table_one t1
 ,table_two t2
where t1.id_field = t2.id_field
order by t1.id_field desc 

Ответ 4

Есть ли разница в производительности или нет, вам нужно использовать то, что более подходит для вашей цели. Ваша цель - получить список Institutions (а не результаты - вам не нужны дополнительные данные). Поэтому выберите "Учреждения", у которых нет результатов... translation - используйте EXISTS.

Ответ 5

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

EDIT: Но это зависит от запроса. Это то, о чем следует судить в каждом конкретном случае.

Ответ 6

Используете ли вы EXISTS как часть коррелированного подзапроса? Если это так, соединение будет почти всегда быстрее.

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

Ответ 7

Собственно, из вашего смутного описания проблемы это звучит для меня, как запрос NOT IN - самый очевидный способ его кодирования:

SELECT *
  FROM Institutions
  WHERE InstitutionID NOT IN (
     SELECT DISTINCT InstitutionID
       FROM Results
     )

Ответ 8

LEFT OUTER JOIN будет работать лучше, чем NOT EXISTS **, но в вашем случае вы хотите делать EXISTS, а использование простой INNER JOIN не совсем реплицирует поведение EXISTS. Если у вас несколько результатов для учреждения, то INNER JOIN вернет несколько строк для этого учреждения. Вы можете обойти это, используя DISTINCT, но тогда EXISTS, вероятно, будет лучше для производительности в любом случае.

** Для тех, кто не знаком с этим методом:

SELECT
     MyTable.MyTableID
FROM
     dbo.MyTable T1
LEFT OUTER JOIN dbo.MyOtherTable T2 ON
     T2.MyTableID = T1.MyTableID
WHERE
     T2.MyOtherTableID IS NULL

эквивалентно

SELECT
     MyTable.MyTableID
FROM
     dbo.MyTable T1
WHERE NOT EXISTS (SELECT * FROM MyOtherTable T2 WHERE T2.MyTableID = T1.MyTableID)

предполагая, что MyOtherTableID является столбцом NOT NULL. Первый метод обычно работает быстрее, чем метод NOT EXISTS.

Ответ 9

Если таблица RESULTS содержит более одной строки за INSTITUTION, EXISTS() имеет дополнительное преимущество, не требуя от вас выбора отдельных Учреждений.

Что касается производительности, я видел, что joins, IN(), and EXISTS() каждый из них является самым быстрым в различных целях. Чтобы найти лучший метод для ваших целей, вы должны проверить.

Ответ 10

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

Ответ 11

Они делают совершенно разные вещи. Чего вы пытаетесь достичь? Это лучше всего определит соответствующую структуру запросов.

Ответ 12

Если вы имеете в виду использование левого (или правого) внешнего соединения или не существует подзапроса, я уверен, что левое внешнее соединение выигрывает по производительности. Например:

SELECT t1.* FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.id = t2.id WHERE t2.id IS NULL

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

Ответ 13

Если вы хотите, чтобы учреждения, у которых не было результатов, то подзапрос "Где нет" будет быстрее, так как он остановится, как только он найдет единственный результат для тех, у кого есть результаты...

Если вы хотите, чтобы учреждения имели результаты, но вы действительно не хотите результатов, то же самое. Используйте подзапрос "Где существует". Он остановится, как только он найдет один результат... Это также гарантирует, что в результирующем наборе будет только одна запись для каждого учреждения, тогда как если бы у вас было учреждение с несколькими результатами, используя join будет требовать, чтобы вы добавляли ключевое слово 'different' или 'Group By', чтобы исключить дубликаты строк продуктов Cartesion, которые будут выведены из нескольких записей Result, которые соответствуют одной записи.

Если вам нужны результаты, выполните JOIN - Inner Join, если вы не хотите видеть вложения без результатов и внешнее соединение, если вы хотите видеть ВСЕ учреждения, в том числе те, у которых нет результатов.