2017-02-16 3 views
0

Итак, у меня в настоящее время есть довольно большая таблица, которую мне нужно часто запрашивать. Эта таблица содержит много столбцов и строк, и мне нужно фильтровать строки на основе 2-х списков, которые размещаются в 2-х виртуальных таблиц, и я хочу результаты, которые соответствуют либо один из нихКакой метод использовать: UNION of JOINS vs LEFT JOINS

enter image description here

Я m делать процедуру для получения результатов, но наша среда разработки не имеет достаточного объема выборки для проверки производительности процедуры. Итак, теперь у меня есть 2 варианта.

  1. Используйте LEFT JOINS, чтобы сделать что-то вроде этого

    SELECT GT.* FROM GiantTable GT 
        LEFT JOIN List1 L1 ON GT.X = L1.X 
        LEFT JOIN List2 L2 ON GT.Y = L2.Y 
    WHERE L1.X IS NOT NULL OR L2.Y IS NOT NULL 
    
  2. Используйте 2 JOIN запросов и UNION результаты

    SELECT GT.* FROM GiantTable GT JOIN List1 L1 ON GT.X = L1.X 
    UNION 
    SELECT GT.* FROM GiantTable GT JOIN List2 L2 ON GT.Y = L1.Y 
    

Я уверен, что второй должен владеть намного лучше, но я хотел бы знать, ошибаюсь ли я

+0

@Jerrad как я уже говорил в этом вопросе «наша среда разработки не хватает размер выборки, чтобы проверить производительность процедуры », и я не являюсь экспертом в инструментах анализа Oracle. – JSantos

+0

Что вы узнали, когда вы googled свой титул? – philipxy

+0

Ваш 1 возвращает разные строки, чем ваш 2. По-видимому, нужные вам строки являются единственными в союзе. Ваш текст довольно неряшлив, но, создавая «фильтр» GT для строк, «которые соответствуют одному из них», мы получаем объединение. Я понимаю, что вы говорите «что-то вроде» re 1, но тогда бессмысленно сравнивать свое время с ответами, возвращающими те же строки, что и 2. Индексы PS имеют большое значение. У вас есть они на GT X & Y? Вы говорите, что Li - это взгляды, и что именно вы имеете в виду, когда говорите, что X & Y - это ПК? Просто, что они уникальны? Знает ли СУБД, когда стоит комбинированный запрос? – philipxy

ответ

1

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

SELECT * 
FROM GiantTable GT 
WHERE (EXISTS (SELECT * FROM List1 L1 WHERE L1.X = GT.X)) 
    OR (EXISTS (SELECT * FROM List2 L2 WHERE L2.Y = GT.Y)) 
+0

С некоторой удачей оптимизатор перепишет это, чтобы он не требовал коррелированных подзапросов. – mathguy

+0

@mathguy Конечно, это было бы так, и удача больше не требуется (20 лет назад удача была основным компонентом в определении скорости вашего запроса, но в этот момент все не-игрушечные РСУБД прошли мимо этого этапа). – dasblinkenlight

+0

Это, очевидно, сделает это, если это полный запрос. Если запрос более сложный, чем этот (если он использует представления, если есть другие объединения, если есть другие сложные условия или вычисления), нам может понадобиться также везение. – mathguy

1

Вы, вероятно, может сделать лучше с

select * 
from gianttable 
where x in (select x from L1) or y in (select y from L2) 

Edit:

сообщает О.П., что эта версия медленнее, чем его первоначальные попытки. Это может быть правдой, особенно если x и y индексируются в gianttable (они являются первичными ключами в своих соответствующих списках, поэтому они являются, индексированными в этих меньших таблицах). То, что мешает, это оператор OR в состоянии where - это означает, что ни одно условие не может использоваться как предикат доступа.

Есть еще одна вещь, которую нужно попробовать ... где индексы должны действительно помочь. Следующий запрос эквивалентен первой попытке OP, а также моей первой попытке (выше) и решению dasblinkenlight. (Это так, потому что x и y являются PK в своих списках, так что нам не нужно обрабатывать null там.)

select * from gianttable where x in (select x from L1) 
union all 
select * from gianttable where y in (select y from L2) and x not in (select x from L1) 
+0

Работа с SQL Server до того, как я всегда чувствовал, что IN имеет очень низкую производительность. Я ошибался или это отличается от Oracle? – JSantos

+0

@JSantos - Это что-то из далекого прошлого. Оптимизатор будет переписывать запросы с IN и EXIST в виде полусоединений - они будут обрабатываться точно так же и будут иметь одинаковую производительность. – mathguy

+0

по моим запросам. Я получаю очень схожую производительность на моем небольшом размере выборки, но с использованием IN он по крайней мере в 10 раз медленнее, тогда два других – JSantos

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