Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 plsql_optimize_level  [new]
clobdoppop
Guest
Всем привет.

Продолжая вчерашнюю проблему, немного модифицировал процедуру, чтобы она выдавала реальный результат
+
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 
Connected as UTEST

SQL> create table table_test( a clob );

Table created

SQL> alter session set plsql_optimize_level=0;

Session altered

SQL> create or replace procedure a_test_9 is
2 v_clob clob;
3 begin
4 v_clob := '0';
5 for i in 1..40000
6 loop
7 v_clob := v_clob || '1';
8 end loop;
9
10 insert into table_test(a) values(v_clob);
11 commit;
12 end;
13 /

Procedure created

SQL> exec a_test_9;

00:00:01.07

PL/SQL procedure successfully completed

SQL> alter session set plsql_optimize_level=2;

Session altered

SQL> create or replace procedure a_test_9 is
2 v_clob clob;
3 begin
4 v_clob := '0';
5 for i in 1..40000
6 loop
7 v_clob := v_clob || '1';
8 end loop;
9
10 insert into table_test(a) values(v_clob);
11 commit;
12 end;
13 /

Procedure created

SQL> exec a_test_9;

00:00:11.42

PL/SQL procedure successfully completed

SQL>

Что модифицирует оптимизатор в таком простом коде?
14 окт 10, 12:57    [9606544]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
-2-
Member

Откуда:
Сообщений: 15330
clobdoppop,

Кеширование клоба? Попробуй в него записать мегабайт.
14 окт 10, 13:00    [9606570]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
clobdoppop
Guest
-2-,
Так пойдет?

+
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 
Connected as UTEST


SQL> alter session set plsql_optimize_level=0;

Session altered

Executed in 0 seconds
SQL> create or replace procedure a_test_9 is
2 v_clob clob;
3 begin
4 dbms_lob.createtemporary( v_clob, true );
5 for i in 1..40000
6 loop
7 v_clob := v_clob || '1';
8 end loop;
9
10 insert into table_test(a) values(v_clob);
11 commit;
12
13 dbms_lob.freetemporary( v_clob );
14 end;
15 /

Procedure created

Executed in 0,093 seconds
SQL> exec a_test_9;

PL/SQL procedure successfully completed

Executed in 12,641 seconds
SQL> alter session set plsql_optimize_level=2;

Session altered

Executed in 0 seconds
SQL> create or replace procedure a_test_9 is
2 v_clob clob;
3 begin
4 dbms_lob.createtemporary( v_clob, true );
5 for i in 1..40000
6 loop
7 v_clob := v_clob || '1';
8 end loop;
9
10 insert into table_test(a) values(v_clob);
11 commit;
12
13 dbms_lob.freetemporary( v_clob );
14 end;
15 /

Procedure created

Executed in 0,078 seconds
SQL> exec a_test_9;

PL/SQL procedure successfully completed

Executed in 1,375 seconds

SQL>
14 окт 10, 13:07    [9606658]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18484
Цикл разворачивает? Тупо присваевает rpad('1', 40000, '1') или что-то вроде этого?
15 окт 10, 03:08    [9611232]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18484
Хотя профайлер этого не подтверждает (да и вообще нагло врет )
t11> connect u1/u1@t11
Connected.
t11> create table t1(a clob);

Table created.

Elapsed: 00:00:00.06
t11> alter session set plsql_optimize_level=1;

Session altered.

Elapsed: 00:00:00.01
t11> declare
  2   c clob;
  3  begin
  4   dbms_profiler.start_profiler('level 1');
  5   dbms_lob.createtemporary(c, true);
  6   for i in 1..40000 loop
  7    c := c || '1';
  8   end loop;
  9   insert into t1 values(c);
 10   commit;
 11   dbms_lob.freetemporary(c);
 12   dbms_profiler.stop_profiler;
 13  end;
 14  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:25.29
t11> alter session set plsql_optimize_level=2;

Session altered.

Elapsed: 00:00:00.00
t11> declare
  2   c clob;
  3  begin
  4   dbms_profiler.start_profiler('level 2');
  5   dbms_lob.createtemporary(c, true);
  6   for i in 1..40000 loop
  7    c := c || '1';
  8   end loop;
  9   insert into t1 values(c);
 10   commit;
 11   dbms_lob.freetemporary(c);
 12   dbms_profiler.stop_profiler;
 13  end;
 14  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.00
t11> @profrep

RUN_COMMENT          UNIT_NAME       LINE# TOTAL_OCCUR             TOTAL_TIME
-------------------- -------------- ------ ----------- ----------------------
level 1              <anonymous>         5           1                 134502
level 1              <anonymous>         6       40001               21001268
level 1              <anonymous>         7       40000            24894660614
level 1              <anonymous>         8           1                      0
level 1              <anonymous>         9           1              106664592
level 1              <anonymous>        10           1                1067271
level 1              <anonymous>        11           1                  11584
level 2              <anonymous>         5           1                 108320
level 2              <anonymous>         6       40001               19486575
level 2              <anonymous>         7       40000             3783216600
level 2              <anonymous>         9           1               19318187
level 2              <anonymous>        10           1                 673508
level 2              <anonymous>        11           1                  10665
level 2              <anonymous>        12           1                   7083

14 rows selected.

Elapsed: 00:00:00.10
profrep взят отсюда
15 окт 10, 05:05    [9611259]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18484
Хотя у меня просто взгляд замылмлся
t11> column level1 format 99999990.999
t11> column level2 format 99999990.999
t11> column diff format 99999990.999
t11> select d2.line#, d2.total_time/1e6 level1, d3.total_time/1e6 level2, (d2.total_time-d3.total_time)/1e6 diff
  2  from plsql_profiler_data d2, plsql_profiler_data d3
  3  where d2.runid < d3.runid and d2.line#=d3.line#
  4  order by 1;

 LINE#        LEVEL1        LEVEL2          DIFF
------ ------------- ------------- -------------
     1         0.000         0.000         0.000
     4         0.000         0.000         0.000
     5         0.135         0.108         0.026
     6        21.001        19.487         1.515
     7     24894.661      3783.217     21111.444
     9       106.665        19.318        87.346
    10         1.067         0.674         0.394
    11         0.012         0.011         0.001
    12         0.000         0.007        -0.007
    13         0.000         0.000         0.000

10 rows selected.

Elapsed: 00:00:00.07
Таки каким-то образом оптимизируется конкатенация
Возможно, связано с выделением памяти в PGA
Сейчас попробую в обратном порядке
15 окт 10, 05:56    [9611275]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18484
Нет
Непричем
RUN_COMMENT          UNIT_NAME       LINE# TOTAL_OCCUR             TOTAL_TIME
-------------------- -------------- ------ ----------- ----------------------
level 2              <anonymous>         5           1                 138749
level 2              <anonymous>         6       40001               18934887
level 2              <anonymous>         7       40000             3881335622
level 2              <anonymous>         9           1               84443405
level 2              <anonymous>        10           1                 390499
level 2              <anonymous>        11           1                  12165
level 1              <anonymous>         5           1                 108747
level 1              <anonymous>         6       40001               20416492
level 1              <anonymous>         7       40000            25459865664
level 1              <anonymous>         8           1                      0
level 1              <anonymous>         9           1               19498601
level 1              <anonymous>        10           1                 456738
level 1              <anonymous>        11           1                  11416
level 1              <anonymous>        12           1                   5499

14 rows selected.
15 окт 10, 06:02    [9611276]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
wurdu
Member

Откуда: Владивосток
Сообщений: 4441
clobdoppop
Что модифицирует оптимизатор в таком простом коде?
Concatenating LOBs
15 окт 10, 07:30    [9611328]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18484
Да, я уже посмотрел твой ответ в другой теме
Интересно, как он это делает
В одну varchar2 переменную все не влезет, т.е. он должен отслеживать заполнение/переполнение и перебрасывать в CLOB-переменную
При этом, если это еще и не тупая константа, а, например, функция, то и отлавливать ошибки, дополнять clob-переменную и перевозбуждать исключение, причем восстанавливать стек ошибок
Хотя это только догадки, конечно.
Возможно, если не константа, то ничего и не оптимизируется
Тестить лень :)
15 окт 10, 07:37    [9611333]     Ответить | Цитировать Сообщить модератору
 Re: plsql_optimize_level  [new]
wurdu
Member

Откуда: Владивосток
Сообщений: 4441
Вячеслав Любомудров
Да, я уже посмотрел твой ответ в другой теме
Интересно, как он это делает
В одну varchar2 переменную все не влезет, т.е. он должен отслеживать заполнение/переполнение и перебрасывать в CLOB-переменную
При этом, если это еще и не тупая константа, а, например, функция, то и отлавливать ошибки, дополнять clob-переменную и перевозбуждать исключение, причем восстанавливать стек ошибок
Хотя это только догадки, конечно.
Возможно, если не константа, то ничего и не оптимизируется
Тестить лень :)
Я бы сказал, интересно как он это делает так медленно с plsql_optimize_level=0.
Там статистики примерно такие:
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
consistent changes                                                   627931
consistent gets                                                      198928
db block changes                                                     628172
db block gets                                                       1703520
free buffer requested                                                158705
lob reads                                                                 0
lob writes                                                           120001
session logical reads                                               1902448
Т.е. он пишет в LOB три раза на каждую итерацию цикла.
С plsql_optimize_level=2
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
consistent changes                                                    40027
consistent gets                                                       80201
db block changes                                                      40258
db block gets                                                         80237
free buffer requested                                                    21
lob reads                                                                 0
lob writes                                                            40002
session logical reads                                                160438
Один раз, как и должно быть. Но в любом случае, надо использовать переменную, если хочется производительности, т.к. оба варианта тормозные.
18 окт 10, 04:33    [9623751]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить