Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Как оптимизировать запрос обновления / 14 сообщений из 14, страница 1 из 1
24.01.2017, 12:39
    #39390191
rigor mortis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
Привет,
что-то затруднился. Требуется выполнить обновление, установив некоторые поля в значения, возвращаемые одной функцией:

Код: plsql
1.
2.
3.
4.
  update table1 t
      set t.field1 = f_function_1(param1 => t.field3),
          t.field2 = f_function_1(param1 => t.field3)
  where (некоторые условия) 



Смущает что приходится одну и ту же функцию вызывать дважды с одними и теми же параметрами на входе. Нельзя ли здесь как-то оптимизировать запрос? t.field2 = t.field1 понятно не прокатит. Курсор не вариант, так как выполняться будет дольше и нет полей чтбы однозначно идентифицировать отдельную запись.
...
Рейтинг: 0 / 0
24.01.2017, 12:50
    #39390203
Вячеслав Любомудров
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
t.field2 = t.field1
...
Рейтинг: 0 / 0
24.01.2017, 12:55
    #39390213
rigor mortis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
Вячеслав Любомудров, t.field2 = t.field1 не сработает, так как возмётся не изменённое значение t.field1 из таблицы и запишется в t.field2.
...
Рейтинг: 0 / 0
24.01.2017, 12:59
    #39390215
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
rigor mortisПривет,
что-то затруднился. Требуется выполнить обновление, установив некоторые поля в значения, возвращаемые одной функцией:

Код: plsql
1.
2.
3.
4.
  update table1 t
      set t.field1 = f_function_1(param1 => t.field3),
          t.field2 = f_function_1(param1 => t.field3)
  where (некоторые условия) 



Смущает что приходится одну и ту же функцию вызывать дважды с одними и теми же параметрами на входе. Нельзя ли здесь как-то оптимизировать запрос? t.field2 = t.field1 понятно не прокатит. Курсор не вариант, так как выполняться будет дольше и нет полей чтбы однозначно идентифицировать отдельную запись.У меня есть подобная задача. Вызов моей функции действительно стоит дорого (в ней множество точечных индексных обращений) - поэтому вместо функции я сделал вызов процедуры с out-параметрами, и решаю данную задачу в PL/SQL с помощью циклов + bulk fetch + коллекций + forall update.
...
Рейтинг: 0 / 0
24.01.2017, 13:03
    #39390217
Вячеслав Любомудров
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
rigor mortisВячеслав Любомудров, t.field2 = t.field1 не сработает, так как возмётся не изменённое значение t.field1 из таблицы и запишется в t.field2.Гоню, конечно
update (select field1, field2, f_function_1(param1 => t.field3) a where ...) set field1=a, field2=a
...
Рейтинг: 0 / 0
24.01.2017, 13:03
    #39390218
Как оптимизировать запрос обновления
rigor mortis,

result cache, deterministic ?
...
Рейтинг: 0 / 0
24.01.2017, 13:10
    #39390224
AmKad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
AmKadrigor mortisПривет,
что-то затруднился. Требуется выполнить обновление, установив некоторые поля в значения, возвращаемые одной функцией:

Код: plsql
1.
2.
3.
4.
  update table1 t
      set t.field1 = f_function_1(param1 => t.field3),
          t.field2 = f_function_1(param1 => t.field3)
  where (некоторые условия) 



Смущает что приходится одну и ту же функцию вызывать дважды с одними и теми же параметрами на входе. Нельзя ли здесь как-то оптимизировать запрос? t.field2 = t.field1 понятно не прокатит. Курсор не вариант, так как выполняться будет дольше и нет полей чтбы однозначно идентифицировать отдельную запись.У меня есть подобная задача. Вызов моей функции действительно стоит дорого (в ней множество точечных индексных обращений) - поэтому вместо функции я сделал вызов процедуры с out-параметрами, и решаю данную задачу в PL/SQL с помощью циклов + bulk fetch + коллекций + forall update.Хотя у меня поля апдейтятся разными значениями, а у тебя одним.
...
Рейтинг: 0 / 0
24.01.2017, 14:24
    #39390290
Вячеслав Любомудров
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
Не, updatable view, оказывается, тоже разложится на 2 вызова
Но ведь есть еще Scalar Subquery Expression
Код: 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.
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.
tst> create function f1(a number) return number as
  2  begin dbms_output.put_line('!!!');
  3        return 10-a;
  4  end;
  5  /

Function created.

tst> create table t1 as select rownum a, rownum+1 b, rownum+2 c from dual connect by level <= 3;

Table created.

tst> set serveroutput on
tst> update (select a, b, f1(c) y from t1 where c = 4) set a=y, b=y;
!!!
!!!

1 row updated.

tst> select * from t1;

         A          B          C
---------- ---------- ----------
         1          2          3
         6          6          4
         3          4          5

tst> rollback;

Rollback complete.

tst> update (select a, b, (select f1(c) from dual) y from t1 where c=4) set a=y, b=y;
!!!

1 row updated.

tst> select * from t1;

         A          B          C
---------- ---------- ----------
         1          2          3
         6          6          4
         3          4          5

tst> update (select a, b, (select f1(c) from dual) y from t1 where c>3) set a=y, b=y;
!!!
!!!

2 rows updated.

tst> select * from t1;

         A          B          C
---------- ---------- ----------
         1          2          3
         6          6          4
         5          5          5

...
Рейтинг: 0 / 0
24.01.2017, 14:40
    #39390304
ora601
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
rigor mortis,

Насколько я помню лучше всего отрабатывает связка result_cache + Scalar SQ, Т.к. result_cache еще и cross-session.
...
Рейтинг: 0 / 0
24.01.2017, 16:14
    #39390417
rigor mortis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
что-то затруднилсяrigor mortis,

result cache, deterministic ?
Спасибо, deterministic подходит
...
Рейтинг: 0 / 0
24.01.2017, 16:35
    #39390450
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
Используй MERGE:

Код: 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.
29.
drop table t1 purge
/
set serveroutput on
create or replace function f1(a number) return number as
begin dbms_output.put_line('!!!');
      return 10-a;
end;
/
create table t1 as select rownum a, rownum+1 b, rownum+2 c from dual connect by level <= 3
/
merge
  into t1 d
  using(
        select rowid rid, f1(c) y from t1 where c = 4
       ) s
  on (
      s.rid = d.rowid
     )
  when matched
    then
      update
         set a = y,
             b = y
/
!!!

1 row merged.

SQL> 



SY.
...
Рейтинг: 0 / 0
24.01.2017, 17:43
    #39390514
rigor mortis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
SYИспользуй MERGE:

Код: 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.
29.
drop table t1 purge
/
set serveroutput on
create or replace function f1(a number) return number as
begin dbms_output.put_line('!!!');
      return 10-a;
end;
/
create table t1 as select rownum a, rownum+1 b, rownum+2 c from dual connect by level <= 3
/
merge
  into t1 d
  using(
        select rowid rid, f1(c) y from t1 where c = 4
       ) s
  on (
      s.rid = d.rowid
     )
  when matched
    then
      update
         set a = y,
             b = y
/
!!!

1 row merged.

SQL> 



SY.

Этот вариант что-то вообще дольше получился на порядок. А с deterministic время выполнения сократилось на 20%.
...
Рейтинг: 0 / 0
24.01.2017, 18:53
    #39390587
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
rigor mortisЭтот вариант что-то вообще дольше получился на порядок. А с deterministic время выполнения сократилось на 20%.

Вeрсия?

11G
Код: 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.
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.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
SQL> set timing off
SQL> set autotrace off
SQL> select banner from v$version
  2  /

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE    11.2.0.3.0      Production
TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

SQL> drop table t1 purge
  2  /

Table dropped.

SQL> set serveroutput on
SQL> create or replace function f1(a number) return number as
  2  begin --dbms_output.put_line('!!!');
  3        return 10-a;
  4  end;
  5  /

Function created.

SQL> create table t1 as select rownum a, rownum+1 b, rownum+2 c from dual connect by level <= 1000000
  2  /

Table created.

SQL> set timing on
SQL> set autotrace on
SQL> merge
  2    into t1 d
  3    using(
  4          select rowid rid, f1(c) y from t1 where mod(c,10) = 0
  5         ) s
  6    on (
  7        s.rid = d.rowid
  8       )
  9    when matched
 10      then
 11        update
 12           set a = y,
 13               b = y
 14  /

100000 rows merged.

Elapsed: 00:00:04.69

Execution Plan
----------------------------------------------------------
Plan hash value: 359177147

-------------------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT      |      | 85923 |  3272K|       |  4245   (1)| 00:00:51 |
|   1 |  MERGE               | T1   |       |       |       |            |          |
|   2 |   VIEW               |      |       |       |       |            |          |
|*  3 |    HASH JOIN         |      | 85923 |  6377K|  3112K|  4245   (1)| 00:00:51 |
|*  4 |     TABLE ACCESS FULL| T1   | 85923 |  2097K|       |   768   (3)| 00:00:10 |
|   5 |     TABLE ACCESS FULL| T1   |   858K|    41M|       |   758   (2)| 00:00:10 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access(ROWID="D".ROWID)
   4 - filter(MOD("C",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
        248  recursive calls
     102767  db block gets
       5908  consistent gets
       2759  physical reads
   26394228  redo size
       2071  bytes sent via SQL*Net to client
       1616  bytes received via SQL*Net from client
          6  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
     100000  rows processed

SQL> commit
  2  /

Commit complete.

Elapsed: 00:00:00.00
SQL> update (select a, b, (select f1(c) from dual) y from t1 where mod(c,10) = 0) set a=y, b=y
  2  /

100000 rows updated.

Elapsed: 00:00:06.11

Execution Plan
----------------------------------------------------------
Plan hash value: 2212140970

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      | 85923 |  3272K|   516K (34)| 01:43:16 |
|   1 |  UPDATE            | T1   |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T1   | 85923 |  3272K|   768   (3)| 00:00:10 |
|   3 |   FAST DUAL        |      |     1 |       |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(MOD("C",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
        102  recursive calls
     102486  db block gets
       2869  consistent gets
          0  physical reads
   25784148  redo size
       1125  bytes sent via SQL*Net to client
       1197  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
     100000  rows processed

SQL> commit
  2  /

Commit complete.

Elapsed: 00:00:00.00
SQL> update t1 set a=f1(c), b=f1(c)  where mod(c,10) = 0
  2  /

100000 rows updated.

Elapsed: 00:00:09.40

Execution Plan
----------------------------------------------------------
Plan hash value: 2927627013

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      | 85923 |  3272K|   768   (3)| 00:00:10 |
|   1 |  UPDATE            | T1   |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T1   | 85923 |  3272K|   768   (3)| 00:00:10 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(MOD("C",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
        182  recursive calls
     204255  db block gets
       2903  consistent gets
          0  physical reads
   45903412  redo size
       1125  bytes sent via SQL*Net to client
       1156  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
     100000  rows processed

SQL> commit
  2  /

Commit complete.

Elapsed: 00:00:00.01
SQL> 



Так что смотри планы и ищи в чем дело.

SY.
...
Рейтинг: 0 / 0
27.01.2017, 13:23
    #39392977
rigor mortis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как оптимизировать запрос обновления
SYrigor mortisЭтот вариант что-то вообще дольше получился на порядок. А с deterministic время выполнения сократилось на 20%.

Вeрсия?

11G
Код: 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.
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.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
SQL> set timing off
SQL> set autotrace off
SQL> select banner from v$version
  2  /

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE    11.2.0.3.0      Production
TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

SQL> drop table t1 purge
  2  /

Table dropped.

SQL> set serveroutput on
SQL> create or replace function f1(a number) return number as
  2  begin --dbms_output.put_line('!!!');
  3        return 10-a;
  4  end;
  5  /

Function created.

SQL> create table t1 as select rownum a, rownum+1 b, rownum+2 c from dual connect by level <= 1000000
  2  /

Table created.

SQL> set timing on
SQL> set autotrace on
SQL> merge
  2    into t1 d
  3    using(
  4          select rowid rid, f1(c) y from t1 where mod(c,10) = 0
  5         ) s
  6    on (
  7        s.rid = d.rowid
  8       )
  9    when matched
 10      then
 11        update
 12           set a = y,
 13               b = y
 14  /

100000 rows merged.

Elapsed: 00:00:04.69

Execution Plan
----------------------------------------------------------
Plan hash value: 359177147

-------------------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT      |      | 85923 |  3272K|       |  4245   (1)| 00:00:51 |
|   1 |  MERGE               | T1   |       |       |       |            |          |
|   2 |   VIEW               |      |       |       |       |            |          |
|*  3 |    HASH JOIN         |      | 85923 |  6377K|  3112K|  4245   (1)| 00:00:51 |
|*  4 |     TABLE ACCESS FULL| T1   | 85923 |  2097K|       |   768   (3)| 00:00:10 |
|   5 |     TABLE ACCESS FULL| T1   |   858K|    41M|       |   758   (2)| 00:00:10 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access(ROWID="D".ROWID)
   4 - filter(MOD("C",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
        248  recursive calls
     102767  db block gets
       5908  consistent gets
       2759  physical reads
   26394228  redo size
       2071  bytes sent via SQL*Net to client
       1616  bytes received via SQL*Net from client
          6  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
     100000  rows processed

SQL> commit
  2  /

Commit complete.

Elapsed: 00:00:00.00
SQL> update (select a, b, (select f1(c) from dual) y from t1 where mod(c,10) = 0) set a=y, b=y
  2  /

100000 rows updated.

Elapsed: 00:00:06.11

Execution Plan
----------------------------------------------------------
Plan hash value: 2212140970

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      | 85923 |  3272K|   516K (34)| 01:43:16 |
|   1 |  UPDATE            | T1   |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T1   | 85923 |  3272K|   768   (3)| 00:00:10 |
|   3 |   FAST DUAL        |      |     1 |       |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(MOD("C",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
        102  recursive calls
     102486  db block gets
       2869  consistent gets
          0  physical reads
   25784148  redo size
       1125  bytes sent via SQL*Net to client
       1197  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
     100000  rows processed

SQL> commit
  2  /

Commit complete.

Elapsed: 00:00:00.00
SQL> update t1 set a=f1(c), b=f1(c)  where mod(c,10) = 0
  2  /

100000 rows updated.

Elapsed: 00:00:09.40

Execution Plan
----------------------------------------------------------
Plan hash value: 2927627013

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      | 85923 |  3272K|   768   (3)| 00:00:10 |
|   1 |  UPDATE            | T1   |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T1   | 85923 |  3272K|   768   (3)| 00:00:10 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(MOD("C",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
        182  recursive calls
     204255  db block gets
       2903  consistent gets
          0  physical reads
   45903412  redo size
       1125  bytes sent via SQL*Net to client
       1156  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
     100000  rows processed

SQL> commit
  2  /

Commit complete.

Elapsed: 00:00:00.01
SQL> 



Так что смотри планы и ищи в чем дело.

SY.

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


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