2010-06-21 3 views
6

Мне интересно узнать наиболее эффективный способ запроса исключения на sql. Например. Существует 2 таблицы (tableA и tableB), которые могут быть объединены в 1 столбец (col1). Я хочу отобразить данные таблицы A для всех строк, которые col1 не существует в таблицеB.SQL: сравнение производительности для исключения (Join vs Not in)

(То есть, другими словами, TableB содержит подмножество col1 из TABLEA. И я хочу, чтобы отобразить TABLEA без данных, которые существуют в TableB)

Допустим, TableB имеет 100 строк в то время как TABLEA гигантский (более чем 1M строк). Я знаю, что «Не в (не существует)» можно использовать, но, возможно, для этого есть более эффективные способы (меньше времени). Я не могу с внешними соединениями?

Отрывки и комментарии кодов очень ценятся.

+0

Какие СУБД? SQL Server, MySQL, Oracle? Возможности оптимизаторов запросов в них различаются. –

+0

Oracle. Я буду удивлен, если будут значительные различия в производительности по сравнению с различными СУБД. – someone

+0

Да, вы будете удивлены. :) – Unreason

ответ

7

Зависит от СУБД. Для Microsoft SQL Server NOT EXISTS is preferred для ВЗАИМОДЕЙСТВИЯ, поскольку он может использовать более эффективное объединение Анти-Semi.

Для Oracle Minus is apparently preferred к NOT EXISTS (где подходит)

Вы должны смотреть на планы выполнения и принять решение.

+0

Спасибо за ответ. СУБД, который меня интересует, - это Oracle. Вы уверены, что Minus более эффективен, чем запрос с присоединением или ответ от inflagranti? – someone

+0

@ masa44 Нет, совсем нет. Хотя ответ inflagranti использует EXCEPT, который * является * Минусом в Oracle. Рекомендация заключалась в том, чтобы посмотреть планы выполнения. –

+1

+1 для рекомендации по расследованию планов выполнения (по реальным данным с обновленной статистикой). Также возникает вопрос, какие индексы присутствуют. – Unreason

1

Вопросы задавались несколько раз. Часто самый быстрый способ сделать это:

SELECT * FROM table1 
WHERE id in (SELECT id FROM table1 EXCEPT SELECT id FROM table2) 

В целом соединение может быть сделано по индексам, где с использованием не в нем, как правило, не может.

+0

Спасибо за ответ. Я не мог найти ранее заданные вопросы. – someone

+0

Это, на мой взгляд, похоже: http://stackoverflow.com/questions/3074862/deleting-all-records-of-a-table-that-are-not-referenced-from-another-table/3074873#3074873 –

+0

Да, это похоже. Но трудно найти этот вопрос, поскольку ему не хватает подробного описания и тегов.Вы знаете это, потому что вы ответили, что один 2 дня назад :) – someone

3

Я предпочитаю использовать

Select a.Col1 
From TableA a 
Left Join TableB b on a.Col1 = b.Col1 
Where b.Col1 Is Null 

Я считаю, что это будет быстрее, как Вы используете ограничение FK (при условии, у вас есть их, конечно)

Образец данных:

create table #a 
(
Col1 int 
) 
Create table #b 
(
col1 int 
) 

insert into #a 
Values (1) 
insert into #a 
Values (2) 
insert into #a 
Values (3) 
insert into #a 
Values (4) 

insert into #b 
Values (1) 
insert into #b 
Values (2) 


Select a.Col1 
From #a a 
Left Join #b b on a.col1 = b.Col1 
Where b.Col1 is null 
+0

Спасибо за ответ, но это решение не работает для меня. Одна из причин: Col1 не может быть нулевым (tableB имеет только Col1). Поэтому ваше решение не дает мне никаких результатов. – someone

+0

@ Masa44 - Ты уверен? Это работает для меня отлично. В качестве примера я добавил некоторые тестовые данные. – codingbadger

+0

Левое соединение часто не является самым быстрым способом для многих баз данных. – HLGEM

-1

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

Если у вас относительно простой запрос, например, в вашем вопросе , существует несколько способов получения результатов в SQL. Каждая собственная система RDBMS распознает ваше намерение и создаст тот же план выполнения, независимо от того, какой синтаксис вы используете (подзапросы с оператором IN или EXISTS, запрос с JOIN, ...)

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

+0

Нет, базы данных не будут создавать тот же план для разных типов запросов, которые имеют одинаковый набор результатов. Если вы посмотрите поставщика по поставщику, вы узнаете, какие из них наиболее эффективны для выполнения конкретных типов запросов. – HLGEM

+0

@HLGEM Вы, очевидно, никогда не смотрели планы исполнения в Oracle в ситуации, о которой идет речь. – zendar

+0

NO I l; ook в планах выполнения на SQL-сервере, где существует огромный различие между такими разными подходами к одному и тому же запросу. И зная, что я знаю, какой тип попробовать сначала. Напишите простейший запрос - это просто плохие советы. ANd «Каждая независимая RDBMS-система распознает ваше намерение и создаст тот же план выполнения, независимо от того, какой синтаксис вы используете», является просто ложным. – HLGEM

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