Можно ли получить хорошую производительность при поиске в большой таблице оракулов списка значений? - PullRequest
0 голосов
/ 12 октября 2018

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

select bar from foo where bar in (:bars);

Цель запроса - просто отразить группузначений для бара вне таблицы foo, чтобы увидеть, какие там есть, а какие нет.Таблица foo огромна, и этот запрос занимает не менее 10 минут, даже если во входном списке всего 5 баров.

Теперь вот еще один запрос, который работает только для одного бара:

select case when exists (select 1 from foo.bar where bar = 'value') then 'Y' else 'N' end from dual;

Это выполняется за небольшую долю секунды и дает мне необходимую информацию.

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

Вопрос в том, как вообще, если я могу получить запрос, который выполняется с производительностью второго запроса, но позволяет мне бросать несколько столбцов в него, как первый запрос??Это важно для меня, потому что обычно проверяют по 10–100 тыс. Баров, причем не только складываются доли секунды, но и каждое соединение с базой данных является точкой отказа.

РЕДАКТИРОВАТЬ: Также в случаеэто имеет значение, запрос выполняется в Java, в частности с классом org.springframework.jdbc.core.JdbcTemplate.Я получаю одинаковые показатели производительности, независимо от того, запускаю ли я запрос через Java или запускаю его в SQL Developer.

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Я думаю, что kanagaraj имел правильную идею, но запрос все еще был таким же медленным, как и раньше, потому что там все еще есть «строка выбора из foo», которая запускает быстрое полное сканирование.Однако модифицированная версия запроса дает мне требуемую производительность (и, конечно, ожидаемые результаты).

with cte as (
select 1, case when exists (select null from foo where bar = 1) then 'Y' else 'N' end from dual
union all
select 2, case when exists (select null from foo where bar = 2) then 'Y' else 'N' end from dual
union all
...
)
select * from cte;

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

0 голосов
/ 12 октября 2018

Со всеми вашими ограничениями для индекса и таблицы. Попробуйте этот запрос ниже, если это одноразовое действие: если его динамическая сборка, как CTE, как показано ниже, и попробуйте

with cte
as
(select 1 bar from dual
union all 
select 2 from dual
union all
select 3 from dual
union all
select 4 from dual
union all
select 5 from dual)

select bar from foo where  exists(select bar from cte where cte.bar=foo.bar);
...