powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Процедура проверки вхождения в таблицы- как ускорить?
24 сообщений из 24, страница 1 из 1
Процедура проверки вхождения в таблицы- как ускорить?
    #39721606
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть процедура на PL/SQL задача которой проверить наличие записей в 3 других таблицах с таким же id.

Вызов процедуры осуществляется следующим образом:

declare
cursor cur is
select id from table1;
begin
for i in cur loop
proc1(id);
end loop;
end;

table1 может содержать от 1000 до 30 млн записей (обновляется периодически полностью).

Есть 3 другие таблицы, содержащие те же id, что и table1.

логика работы proc1 следующая:
1. Проверить наличие записи с table1.id в table2, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table2')
2. Если в table2 нет записи с table1.id идем проверять в table3, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table3')
3. Если в table3 нет записи с table1.id идем проверять в table4, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table4')
4. Если в table4 нет записи с table1.id идем проверять, то в результирующую таблица table_result пишется результат (id,'нет нигде')

размер таблиц примерно:
table2 - 55 млн записей
table3 - 2 млн записей
table4 - 7 млн записей

Для 300 тыс записей в table1 процедура работает порядка 10 мин, а хочется чтобы это укладывалось в десятки секунд, т.е. чтобы скорость была порядка 10 тыс записей в секунду.

Каким образом можно кардинально ускорить работы процедуры?
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721613
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimetsКаким образом можно кардинально ускорить работы процедуры?

Если содержимое table1 можно уничтожить после работы, то выкинуть функцию и использовать
MERGE.
Если нельзя - придётся искать где же ты облажался при реализации простой логики.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721620
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovDimetsКаким образом можно кардинально ускорить работы процедуры?

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


table1 уничтожить нельзя((

запросы по table2,table3,table4 выполняются за 3-5 мс в каждой
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721623
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimetsзапросы по table2,table3,table4 выполняются за 3-5 мс в каждой

А для скорости в 10000 записей в секунду они должны выполняться по 0,1-0,03 мс. Почувствуй
разницу.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721626
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovDimetsзапросы по table2,table3,table4 выполняются за 3-5 мс в каждой

А для скорости в 10000 записей в секунду они должны выполняться по 0,1-0,03 мс. Почувствуй
разницу.


И как обеспечить такую скорость выполнения?
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721642
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimetsлогика работы proc1 следующая:
1. Проверить наличие записи с table1.id в table2, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table2')
2. Если в table2 нет записи с table1.id идем проверять в table3, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table3')
3. Если в table3 нет записи с table1.id идем проверять в table4, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table4')
4. Если в table4 нет записи с table1.id идем проверять, то в результирующую таблица table_result пишется результат (id,'нет нигде')
Каким образом можно кардинально ускорить работы процедуры?
Зависит от.
К примеру, можно так (insert или merge - по потребности, индексы по id на всех таблицах - обязательны):
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
insert into table_result
select id
        , coalesce( (select 'есть в table2' x from dual where exists (select null from table2 where id = t.id))
                  , (select 'есть в table3' x from dual where exists (select null from table3 where id = t.id))
                  , (select 'есть в table4' x from dual where exists (select null from table4 where id = t.id))
                  ,  'нет нигде'
                  )
  from table1 t



Если индексов нет, но есть много памяти и уверенность в уникальности id - можно внешние hash join-ы и выбирать результат тем же coalesce в стиле:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
insert into table_result
select /*+ leading(t, t3, t4, t2) use_hash(t3) use_hash(t4) use_hash(t2)*/
       t.id
     , coalesce( nvl2(t2.id,'есть в table2', null)
               , nvl2(t3.id,'есть в table3', null)
               , nvl2(t4.id,'есть в table4', null)
               ,  'нет нигде'
               )
  from table1 t
     , table2 t2
     , table3 t3
     , table4 t4
 where t.id = t2.id(+)
   and t.id = t3.id(+)
   and t.id = t4.id(+)
;



Этот вариант, при наличии навыков, можно еще и параллелить.

Также можно попробовать самовыразиться на ANSI:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
insert into table_result
select t.id
     , coalesce( nvl2(t2.id,'есть в table2', null)
               , nvl2(t3.id,'есть в table3', null)
               , nvl2(t4.id,'есть в table4', null)
               ,  'нет нигде'
               )
  from table1 t 
  left join table2 t2 on t.id = t2.id
  left join table3 t3 on t.id = t3.id and t2.id is null
  left join table4 t4 on t.id = t4.id and t3.id is null
;


но тут лучше иметь индексы по t3, t4

Если же требуется именно процедурой и именно построчно - то
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure proc1(p_id) is
begin
  for i in (select 'есть в table2' x from dual where exists (select null from table2 where id = p_id))
  loop
    insert into table_result values(p_id, i.x);
    return;
  end loop;
  ...
  for i in (select 'есть в table4' x from dual where exists (select null from table4 where id = p_id))
  loop
    insert into table_result values(p_id, i.x);
    return;
  end loop;
  insert into table_result values(p_id, 'нет нигде');
end;
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721645
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimetsИ как обеспечить такую скорость выполнения?
Процедурой? Никак.
Зато можно воспользоваться dbms_parallel_execute.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721656
KOT MATPOCKuH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А триггер не поможет?
Тогда и процедуру вызывать не нужно - результат всегда готов
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721664
SkilledJunior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KOT MATPOCKuH,

Та же проблема что и с процедурой, для каждой строки выполняется несколько отдельных DML операций.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721668
SkilledJunior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как вариант, добавить поле в table1 и прогнать три update, накатывая последовательно table4, table3, table2. Строку 'есть в table2/3/4' заменить на код 2,3,4.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721735
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousDimetsИ как обеспечить такую скорость выполнения?
Процедурой? Никак.
Зато можно воспользоваться dbms_parallel_execute.

В какой части воспользоваться?
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721736
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KOT MATPOCKuHА триггер не поможет?
Тогда и процедуру вызывать не нужно - результат всегда готов

не поможет((
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721753
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousDimetsлогика работы proc1 следующая:
1. Проверить наличие записи с table1.id в table2, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table2')
2. Если в table2 нет записи с table1.id идем проверять в table3, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table3')
3. Если в table3 нет записи с table1.id идем проверять в table4, если такая запись есть, то в результирующую таблица table_result пишется результат (id,'есть в table4')
4. Если в table4 нет записи с table1.id идем проверять, то в результирующую таблица table_result пишется результат (id,'нет нигде')
Каким образом можно кардинально ускорить работы процедуры?
Зависит от.
К примеру, можно так (insert или merge - по потребности, индексы по id на всех таблицах - обязательны):
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
insert into table_result
select id
        , coalesce( (select 'есть в table2' x from dual where exists (select null from table2 where id = t.id))
                  , (select 'есть в table3' x from dual where exists (select null from table3 where id = t.id))
                  , (select 'есть в table4' x from dual where exists (select null from table4 where id = t.id))
                  ,  'нет нигде'
                  )
  from table1 t



Если индексов нет, но есть много памяти и уверенность в уникальности id - можно внешние hash join-ы и выбирать результат тем же coalesce в стиле:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
insert into table_result
select /*+ leading(t, t3, t4, t2) use_hash(t3) use_hash(t4) use_hash(t2)*/
       t.id
     , coalesce( nvl2(t2.id,'есть в table2', null)
               , nvl2(t3.id,'есть в table3', null)
               , nvl2(t4.id,'есть в table4', null)
               ,  'нет нигде'
               )
  from table1 t
     , table2 t2
     , table3 t3
     , table4 t4
 where t.id = t2.id(+)
   and t.id = t3.id(+)
   and t.id = t4.id(+)
;



Этот вариант, при наличии навыков, можно еще и параллелить.

Также можно попробовать самовыразиться на ANSI:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
insert into table_result
select t.id
     , coalesce( nvl2(t2.id,'есть в table2', null)
               , nvl2(t3.id,'есть в table3', null)
               , nvl2(t4.id,'есть в table4', null)
               ,  'нет нигде'
               )
  from table1 t 
  left join table2 t2 on t.id = t2.id
  left join table3 t3 on t.id = t3.id and t2.id is null
  left join table4 t4 on t.id = t4.id and t3.id is null
;


но тут лучше иметь индексы по t3, t4

Если же требуется именно процедурой и именно построчно - то
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure proc1(p_id) is
begin
  for i in (select 'есть в table2' x from dual where exists (select null from table2 where id = p_id))
  loop
    insert into table_result values(p_id, i.x);
    return;
  end loop;
  ...
  for i in (select 'есть в table4' x from dual where exists (select null from table4 where id = p_id))
  loop
    insert into table_result values(p_id, i.x);
    return;
  end loop;
  insert into table_result values(p_id, 'нет нигде');
end;




Индексы есть такие везде. Попробовал вариант с coalesce, ускорение есть, но не на порядок как требуется
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721840
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
declare
cursor cur is
select id from table1;
begin
for i in cur loop
proc1(id);
end loop;
end;

Можно ли каким то образом сделать несколько параллельных вызовов proc1, например 10 шт, каждая из которых будет запускаться со своим уникальным id?
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721841
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimetsМожно ли каким то образом сделать несколько параллельных вызовов proc1, например 10 шт, каждая из которых будет запускаться со своим уникальным id?Можно.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721845
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ElicDimetsМожно ли каким то образом сделать несколько параллельных вызовов proc1, например 10 шт, каждая из которых будет запускаться со своим уникальным id?Можно.

А пример подскажите?
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721863
anvano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А всё-таки, что у вас в proc1 такого внутри страшного ?

Я накидал синтетический тест, при миллионе записей в table1 и при 70 миллионах в table2
даже ваша построчная обработка обрабатывает около 10-12 тыс записей в секунду.

То-ли индексы у вас кривые,
то-ли проверяется в реальности не число, а какая-нибудь строка LIKE-ом
то ли всё время уходит на вставку в table_result (попробовать накапливать и BULK-ами скидывать)

ощущение, что где-то в proc1 в логике косяк и в циклах делаются ненужные вещи.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721867
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
anvanoи в циклах делаются ненужные вещиНапример, оптимизированный fetch по 100.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721870
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimetsА пример подскажите?Экстенсификация - это тупиковый путь развития.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721927
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
anvanoА всё-таки, что у вас в proc1 такого внутри страшного ?

Я накидал синтетический тест, при миллионе записей в table1 и при 70 миллионах в table2
даже ваша построчная обработка обрабатывает около 10-12 тыс записей в секунду.

То-ли индексы у вас кривые,
то-ли проверяется в реальности не число, а какая-нибудь строка LIKE-ом
то ли всё время уходит на вставку в table_result (попробовать накапливать и BULK-ами скидывать)

ощущение, что где-то в proc1 в логике косяк и в циклах делаются ненужные вещи.

Ничего страшного там по сути нет, вот такой запрос там идет и потом Insert

select coalesce( (select 'TBL2' x from dual where
exists (select null from table2@y where rid = p_rid and aid=p_aid and cid=p_cid))
, (select 'TBL3' x from dual where
exists (select null from table3@y where rid = p_rid and aid=p_aid))
, (select 'TBL4' x from dual where exists (select null from table4@y where rid = p_rid and aid=p_aid))
, 'NA'
) into l_check_result_code
from dual;

вызов процедуры:
declare
cursor cur is
select rid, aid
from table1;
begin
for i in cur loop
proc1(i.rid,i.aid,1); --1 это p_cid
end loop;
end;
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721929
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimets
Код: plsql
1.
@y

Вот и корень зла.
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721954
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ElicDimets
Код: plsql
1.
@y

Вот и корень зла.

провел эксперимент скопировав таблицы в свою схему

Итого при следующих параметрах:
table1 - 281 065 records
table2 - 24 999 999 records
table3 - 2 434 885 records
table4 - 7 289 199 records

Время работы - 00:02:22.827602, примерно 281065/144 = 1951 rec per sec

затем убрал Insert в proc1 и время стало 26 сек - 281065/26 = 10810 rec per sec

Вот без insert это приемлемое время, что с этим можно поделать?
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721965
Dimets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DimetsElicпропущено...
Вот и корень зла.

провел эксперимент скопировав таблицы в свою схему

Итого при следующих параметрах:
table1 - 281 065 records
table2 - 24 999 999 records
table3 - 2 434 885 records
table4 - 7 289 199 records

Время работы - 00:02:22.827602, примерно 281065/144 = 1951 rec per sec

затем убрал Insert в proc1 и время стало 26 сек - 281065/26 = 10810 rec per sec

Вот без insert это приемлемое время, что с этим можно поделать?

индексы есть на всех таблицах table2,table3,table4
...
Рейтинг: 0 / 0
Процедура проверки вхождения в таблицы- как ускорить?
    #39721972
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimetsчто с этим можно поделать?Купить рабочее время консультанта.
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Процедура проверки вхождения в таблицы- как ускорить?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]