powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Производительность вставки
23 сообщений из 23, страница 1 из 1
Производительность вставки
    #39419694
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет всем!
У нас с 2-м подрядчиком на проекте возник спор по поводу производительности разных способов вставки больших данных в таблицу.
Есть тип:
Код: plsql
1.
CREATE OR REPLACE TYPE num_tab AS TABLE OF NUMBER;


Есть процедура, которая принимает себе на вход некий ИД и данный тип:
Код: plsql
1.
PROCEDURE test(p_id NUMBER, p_nested_ids num_tab);



Способ вставки № 1:
Код: plsql
1.
2.
3.
4.
5.
FORALL i IN p_nested_ids.first .. p_nested_ids.last
  INSERT INTO test_table
    (id, nested_id)
  VALUES
    (p_id, p_nested_ids(i));


Способ вставки № 2:
Код: plsql
1.
2.
3.
INSERT INTO test_table(id, nested_id)
SELECT p_id, column_value
FROM TABLE(p_nested_ids);



Пытался найти сравнение в гугле - нашел много сравнений между FOR и FORALL, а по теме - ничего.
Помогите разобраться, что в действительности быстрее выходит, и почему.
Спасибо ;-)
...
Рейтинг: 0 / 0
Производительность вставки
    #39419724
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krupt,

вроде бы, еще быстрее будет, при +APPEND или +APPEND_VALUES
...
Рейтинг: 0 / 0
Производительность вставки
    #39419735
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Производительность вставки
    #39419741
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
--Eugene--krupt,

вроде бы, еще быстрее будет, при +APPEND или +APPEND_VALUES

Тут как в анекдоте про динозавра: c вероятностью 1/2 или будет быстрее или 1/2, что через какое-то время от append'а сервер вообще загнется колом.

Помогите разобраться, что в действительности быстрее выходит, и почему.

Могу предложить 100% работающий способ: по дороге на работу зайти в магазин, купить часы-секундомер, засечь время

Будем рады, если Вы нам сообщите о результатах. Нам тоже интересно.
...
Рейтинг: 0 / 0
Производительность вставки
    #39419747
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev--Eugene--krupt,

вроде бы, еще быстрее будет, при +APPEND или +APPEND_VALUES Тут как в анекдоте про динозавра: c вероятностью 1/2 или будет быстрее или 1/2, что через какое-то время от append'а сервер вообще загнется колом.Ну почему? Если эта таблица-журнал, в которую постоянно что-то пишется и ничего не удаляется, а, к примеру, дропаются лишь старые партиции.

Не знаю, правда, как DIRECT-PATH INSERT ведет себя при конкурентной вставке..
...
Рейтинг: 0 / 0
Производительность вставки
    #39419772
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
--Eugene-- dml single insert/select or bulk collect/forall
Тут сравнивается вставка из nested table и вставка из реальной таблицы. А у нас цель проверить вставку из nested table двумя разными способами.
...
Рейтинг: 0 / 0
Производительность вставки
    #39419783
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
--Eugene--Leonid Kudryavtsevпропущено...
Тут как в анекдоте про динозавра: c вероятностью 1/2 или будет быстрее или 1/2, что через какое-то время от append'а сервер вообще загнется колом.Ну почему? Если эта таблица-журнал, в которую постоянно что-то пишется и ничего не удаляется, а, к примеру, дропаются лишь старые партиции.

Не знаю, правда, как DIRECT-PATH INSERT ведет себя при конкурентной вставке..

В нашем случае таблица - не журнал. В ней данные могут регулярно добавляться/удаляться.
...
Рейтинг: 0 / 0
Производительность вставки
    #39419787
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Leonid KudryavtsevМогу предложить 100% работающий способ: по дороге на работу зайти в магазин, купить часы-секундомер, засечь время
Будем рады, если Вы нам сообщите о результатах. Нам тоже интересно.

Данный способ не ответит на вопрос: - Почему быстрее?
...
Рейтинг: 0 / 0
Производительность вставки
    #39419822
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krupt,

Насколько я понимаю, FORALL будет медленнее, поскольку это - так или иначе - несколько INSER-ов, объединенных в пачку (только без переключения контекста).
А INSERT SELECT - это все-таки одно SQL-выражение.

Думаю, проще сделать Proof Of Concept, чем ждать тут ответа.
...
Рейтинг: 0 / 0
Производительность вставки
    #39419869
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
еще про производительность вставки: Parallel DML - Conventional (non-direct-path) Inserts As Select
...
Рейтинг: 0 / 0
Производительность вставки
    #39419922
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
CREATE OR REPLACE PACKAGE BODY test_package IS

  PROCEDURE test1
  (
    p_id         NUMBER,
    p_nested_ids num_tab
  ) AS
  BEGIN
    FORALL i IN p_nested_ids.first .. p_nested_ids.last
      INSERT INTO test_table
        (id, nested_id)
      VALUES
        (p_id, p_nested_ids(i));
  END;

  PROCEDURE test2
  (
    p_id         NUMBER,
    p_nested_ids num_tab
  ) AS
  BEGIN
    INSERT INTO test_table
      (id, nested_id)
      SELECT p_id, column_value
      FROM TABLE(p_nested_ids);
  END;

END;



Для проверки использовался следующий анонимный PL/SQL-блок:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
DECLARE
  v_ids num_tab := num_tab();
BEGIN
  FOR i IN 1 .. 4175000
  LOOP
    v_ids.extend;
    v_ids(v_ids.last) := i;
  END LOOP;
  test_package.test1(1, v_ids);
END;


Получились вот такие результаты:
ПроцедураТип вставкиКоличество записейВремя 1 (секунд)Время 2 (секунд)Время 3 (секунд)Время 4 (секунд)Время 5 (секунд)Ср. время (секунд)test1FORALL10 000 00048.6938.40627.2737.98426.12935.6958test1FORALL4 175 00010.76810.68110.67810.9110.95710.7988test1FORALL1 000 0002.5332.5342.5952.512.6252.5594test2INSERT .. SELECT FROM TABLE..4 180 000+ORA-22813: значение операнда превышает системный лимитtest2INSERT .. SELECT FROM TABLE..4 175 00010.77710.97511.05510.90910.72210.8876test2INSERT .. SELECT FROM TABLE..1 000 0002.6052.7142.522.4922.5852.5832
...
Рейтинг: 0 / 0
Производительность вставки
    #39419923
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
--Eugene--Насколько я понимаю, FORALL будет медленнее, поскольку это - так или иначе - несколько INSER-ов, объединенных в пачку (только без переключения контекста).
А INSERT SELECT - это все-таки одно SQL-выражение.


Не смешите мои тапочки. Они и так уже порвались. Пожалейте их.

Про +append, krupt, Вам уже ответил.

kruptLeonid KudryavtsevМогу предложить 100% работающий способ: по дороге на работу зайти в магазин, купить часы-секундомер, засечь время
Будем рады, если Вы нам сообщите о результатах. Нам тоже интересно.

Данный способ не ответит на вопрос: - Почему быстрее?

Вы сначала просветите нас, кто же на самом деле быстрее.
А мы потом начнем думать, почему.
...
Рейтинг: 0 / 0
Производительность вставки
    #39419936
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krupt,
Пытаться придумать ответ "почему" нужно?
...
Рейтинг: 0 / 0
Производительность вставки
    #39419966
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Leonid Kudryavtsevkrupt,
Пытаться придумать ответ "почему" нужно?
Реализация обоих способов сделана внутри БД Oracle сделана по-разному, т.к. при втором способе получаем EXCEPTION.
Но почему результаты одинаковы не совсем понятно.
FORALL специальная команда и реализована без использования цикла.
...
Рейтинг: 0 / 0
Производительность вставки
    #39419996
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kruptНо почему результаты одинаковы не совсем понятно.

Обе команды вставляют одни и те же данные, в одну и ту же таблицу, одной и той же структуры.

kruptFORALL специальная команда и реализована без использования цикла.

ну вот она и отработало "более грамотно"
...
Рейтинг: 0 / 0
Производительность вставки
    #39420034
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
kruptНо почему результаты одинаковы не совсем понятно.потому что разница настолько мала, что ею можно пренебресь в сравнении с основными общими временными затратами на саму вставку в таблицу
...
Рейтинг: 0 / 0
Производительность вставки
    #39420099
Cavia porcellus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Поделюсь своими изысканиями.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
clear screen
set feedback off
set autoprint off
var v_count number;
exec :v_count := 1000000;
prompt Пример1: Использование FOR
set timing on
declare
  v_tab numbers_ct := numbers_ct();
begin
  -- заполнение коллекции
  v_tab.extend(:v_count);
  for n in 1 .. :v_count
  loop
    v_tab(n) := n;
  end loop;
    
  -- вставка в таблицу
  for n in v_tab.first .. v_tab.last
  loop
    insert into test1 (testnum) values (v_tab(n));
  end loop;
end;
/
set timing off
truncate table test1 reuse storage;
prompt Пример2: Использование FORALL
set timing on
declare
  v_tab numbers_ct := numbers_ct();
begin
  -- заполнение коллекции
  v_tab.extend(:v_count);
  for n in 1 .. :v_count
  loop
    v_tab(n) := n;
  end loop;
     
  -- вставка в таблицу
  forall n in v_tab.first .. v_tab.last
    insert into test1 (testnum) values (v_tab(n));
end;
/
set timing off
truncate table test1 reuse storage;
 
prompt Пример3: insert select from table(cast ...)
set timing on
declare
  v_tab numbers_ct := numbers_ct();
begin
  -- заполнение коллекции
  v_tab.extend(:v_count);
  for n in 1 .. :v_count
  loop
    v_tab(n) := n;
  end loop;
     
  -- вставка в таблицу
    insert into test1 (testnum)
      select * from table(cast(v_tab as numbers_ct));
end;
/
set timing off
truncate table test1 reuse storage;



Результаты выполнения скрипта:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Пример1: Использование FOR
Executed in 32,802 seconds

Пример2: Использование FORALL
Executed in 1,462 seconds

Пример3: insert select from table(cast ...)
Executed in 1,664 seconds

А если попробовать увеличить размер коллекции до 10000000, получим вот такие результаты:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Пример1: Использование FOR
Executed in 331,219 seconds
Пример2: Использование FORALL
Executed in 15,874 seconds
Пример3: insert select from table(cast ...)
ORA-22813: operand value exceeds system limits
ORA-22813: operand value exceeds system limits
ORA-06512: at line 12
...
Рейтинг: 0 / 0
Производительность вставки
    #39420106
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cavia porcellusПример3: insert select from table(cast ...)
ORA-22813: operand value exceeds system limits
ORA-22813: operand value exceeds system limits
ORA-06512: at line 12

Ну наконец пришли к основному критерию когда что целесообразней (память она не резиновая).

SY.
...
Рейтинг: 0 / 0
Производительность вставки
    #39420123
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Похоже, бинды каким-то образом копируются из PL-контекста в SQL-контекст на время исполнения выражения.
То есть, доступ к ним происходит совсем не по ссылке.
И если делать SELECT * FROM TABLE(:T), где размер T велик, ее содержимое будет скопировано, и, соответственно, будет выделено большое количество памяти второй раз.

Не? )
...
Рейтинг: 0 / 0
Производительность вставки
    #39420200
Kumotori
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тоже решил потестить, но заглянуть со стороны трейса :

Для "FORALL"----- Current SQL Statement for this session (sql_id=ahjqwf9r2qr56) -----
INSERT INTO TEST_TABLE1 (ID, NESTED_ID) VALUES (:B2 , :B1 )

STAT #392845784 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL TEST_TABLE1 (cr=3630 pr=0 pw=0 time=1903643 us)'


Для INSERT...SELECT----- Current SQL Statement for this session (sql_id=0qn4vrgq35qga) -----
INSERT INTO TEST_TABLE2 (ID, NESTED_ID) SELECT :B2 , COLUMN_VALUE FROM TABLE(:B1 )

STAT #392844608 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL TEST_TABLE2 (cr=3633 pr=0 pw=0 time=2062626 us)'
STAT #392844608 id=2 cnt=1000000 pid=1 pos=1 obj=0 op='COLLECTION ITERATOR PICKLER FETCH (cr=0 pr=0 pw=0 time=522351 us cost=29 size=200 card=100)'


Получается, в случае INSERT...SELECT на вставку 1мил. записей уходит те же 2 секунды (time=1903643 vs. time=2062626), но добавляется 0.5 секунды (time=522351) на феч колекции.

вот что пишет Бурлесон по этому поводу:
Бурлесон пишетThe execution plan step "COLLECTION ITERATOR (PICKLER FETCH)" is the optimizer plan operation showing use of the dbms_pickler package, a PL/SQL package which is used to get TDS (Type Descriptor Source) of a object.
...
...there are several reported memory leak issues with pickler fetches, even in Oracle 11g.


С учетом всего — FORALL быстрее и безопаснее.
...
Рейтинг: 0 / 0
Производительность вставки
    #39420213
Фотография --Eugene--
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KumotoriБурлесон пишетThe execution plan step "COLLECTION ITERATOR (PICKLER FETCH)" is the optimizer plan operation showing use of the dbms_pickler package, a PL/SQL package which is used to get TDS (Type Descriptor Source) of a object. Results for DBMS_PICKLER: No results found
...
Рейтинг: 0 / 0
Производительность вставки
    #39420227
Kumotori
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
--Eugene--Results for DBMS_PICKLER: No results found

Да, недокументировано.
Потому я и сослался на Бурлесона, а не на оф.доку.
А пакет в совей базе поищи.
...
Рейтинг: 0 / 0
Производительность вставки
    #39421163
krupt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kumotori,

Спасибо
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Производительность вставки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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