Оптимизатор должен основывать свое решение на количестве элементов в списке и количестве строк в таблице.Если в таблице миллионы строк, а в списке даже пара тысяч элементов, я бы, как правило, ожидал, что он будет использовать индекс для выполнения нескольких тысяч однострочных поисков.Если таблица содержит несколько тысяч строк, а список содержит пару тысяч элементов, я ожидаю, что оптимизатор выполнит полное сканирование таблицы.В середине, конечно, происходит все интересное и становится все труднее точно определить, какой план выберет оптимизатор.
В целом, однако, динамическое построение такого рода запросаЭто будет проблематично с точки зрения производительности не из-за того, насколько дорогое выполнение конкретного запроса, а из-за того, что генерируемые вами запросы не являются общими.Поскольку вы не можете использовать переменные связывания (или, если вы используете переменные связывания, вам потребуется другое количество переменных связывания).Это заставляет Oracle выполнять довольно дорогой жесткий анализ запроса каждый раз и оказывает давление на ваш общий пул, что, вероятно, вытеснит другие запросы с совместным доступом, что вызовет более сложный анализ в системе.Как правило, вам лучше будет выбросить данные, с которыми вы хотите сопоставить, во временную таблицу (или даже в постоянную таблицу), чтобы ваш запрос можно было сделать разделяемым и проанализировать только один раз.
К комментарию Бранко, в то время как Oracle ограничен 1000 литералами в списке IN
, то есть, только если вы используете «нормальный» синтаксис, то есть
WHERE projectID IN (1,2,3,...,N)
Если вы используетеоднако синтаксис кортежа, который вы опубликовали ранее, может содержать неограниченное количество элементов.
Так, например, я получу ошибку, если создам запрос с 2000 элементами в IN
list
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_sql_stmt varchar2(32000);
3 l_cnt integer;
4 begin
5 l_sql_stmt := 'select count(*) from emp where empno in (';
6 for i in 1..2000
7 loop
8 l_sql_stmt := l_sql_stmt || '(1),';
9 end loop;
10 l_sql_stmt := rtrim(l_sql_stmt,',') || ')';
11 -- p.l( l_sql_stmt );
12 execute immediate l_sql_stmt into l_cnt;
13* end;
SQL> /
declare
*
ERROR at line 1:
ORA-01795: maximum number of expressions in a list is 1000
ORA-06512: at line 12
Но только если я использую синтаксис кортежа
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_sql_stmt varchar2(32000);
3 l_cnt integer;
4 begin
5 l_sql_stmt := 'select count(*) from emp where (empno,empno) in (';
6 for i in 1..2000
7 loop
8 l_sql_stmt := l_sql_stmt || '(1,1),';
9 end loop;
10 l_sql_stmt := rtrim(l_sql_stmt,',') || ')';
11 -- p.l( l_sql_stmt );
12 execute immediate l_sql_stmt into l_cnt;
13* end;
SQL> /
PL/SQL procedure successfully completed.