powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / group + join или наоборот?
4 сообщений из 4, страница 1 из 1
group + join или наоборот?
    #39305778
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть запрос

Код: 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.
INSERT /*+append parallel(3,3)*/  INTO TMP_
  (
    C_DATE,
    C_ACC,
    C_TURNOVER_DBT,
    C_TURNOVER_DBT_LCL,
    C_TURNOVER_CRT,
    C_TURNOVER_CRT_LCL,
    C_BALANCE,
    C_BALANCE_LCL,
    STEP
  )
with rec as (--обработанные проводки
  select collection_id, 
  trunc(c_date) c_date, 
  sum(C_TURNOVER_DBT) C_TURNOVER_DBT, 
  sum(C_TURNOVER_DBT_LCL) C_TURNOVER_DBT_LCL,
  sum(C_TURNOVER_CRT) C_TURNOVER_CRT, 
  sum(C_TURNOVER_CRT_LCL) C_TURNOVER_CRT_LCL,
  sum(C_BALANCE) C_BALANCE, 
  sum(C_BALANCE_LCL) C_BALANCE_LCL
  from (
      select  r2.*,
      --баланс считаем только для последней записи 
       case when rn = 1 then nvl(C_START_SUM,0) +     direction * nvl(C_SUMMA,0)     end as C_BALANCE,
       case when rn = 1 then nvl(C_START_SUM_NAT,0) + direction * nvl(C_SUMMA_NAT,0) end as C_BALANCE_LCL
            from (
            select /*+ full(r) full(r.t) full(r.t.DA) full(r.t.DC) PARALLEL(3,3) */
                   r.*
                  ,row_number() over (partition by r.collection_id, trunc(r.c_date) order by r.c_date desc, r.id desc) as rn --последняя запись на ключе Счет+Опердень
                  ,case when C_DT = '1' then C_SUMMA else 0 end C_TURNOVER_DBT,
                   case when C_DT = '1' then C_SUMMA_NAT else 0 end C_TURNOVER_DBT_LCL,
                   case when C_DT = '0' then C_SUMMA else 0 end C_TURNOVER_CRT,
                   case when C_DT = '0' then C_SUMMA_NAT else 0 end C_TURNOVER_CRT_LCL,
                   case when C_DT = '1' then -1 else 1 end direction --множитель для остатка 
            from records_v --view - join records1 и records2
            where r.c_date >= date '2016-01-01' and r.c_date <date '2016-01-10' +1 
              --отбросить нулевые строки 
              and NOT (nvl(C_START_SUM,0) = 0 and nvl(C_SUMMA,0) = 0 and nvl(C_START_SUM_NAT,0) = 0 and nvl(C_SUMMA_NAT,0) = 0   
                       and (c_type_oper = 2050157 or c_type_oper is null)
                       )
            ) r2
      ) r3
  group by collection_id,trunc(c_date)
),
ac as --уникальное соответствие id = c_arc_move
 (select /*+ full(ac) PARALLEL(3,3) */
  distinct id, c_arc_move
  from ac_
  )
select /*+ parallel(3,3)*/
C_DATE,
ac.id c_acc,
sum(nvl(C_TURNOVER_DBT,0)),
sum(nvl(C_TURNOVER_DBT_LCL,0)),
sum(nvl(C_TURNOVER_CRT,0)),
sum(nvl(C_TURNOVER_CRT_LCL,0)),
sum(nvl(C_BALANCE,0)),
sum(nvl(C_BALANCE_LCL,0)),
  1 step
from ac inner join rec on ac.c_arc_move = rec.collection_id
group by --во избежание ситуации, когда внутри одной даты два разных collection_id по одному счету
          C_DATE, ac.id
;


его план в рантайме такой:

Код: 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.
  SELECT id, parent_id, LPAD (' ', LEVEL - 1) || operation || ' ' ||
 options operation, object_name
 FROM (
 SELECT id, parent_id, operation, options, object_name
  FROM gv$sql_plan
  WHERE address = '0000000E8EFD5978'
  AND hash_value = 2898422194
  AND child_number = 0
  )
  START WITH id = 0
  CONNECT BY PRIOR id = parent_id
;

0  INSERT STATEMENT  
1 0  LOAD AS SELECT  
2 1   PX COORDINATOR  
3 2    PX SEND QC (RANDOM) :TQ10006
4 3     HASH GROUP BY                       +1++++++++++
5 4      PX RECEIVE  
6 5       PX SEND HASH :TQ10005
7 6        HASH GROUP BY                       +2++++++++++ 
8 7         HASH JOIN  
9 8          PX RECEIVE  
10 9           PX SEND BROADCAST :TQ10003
11 10            VIEW  
12 11             SORT GROUP BY                        +3++++++++++
13 12              PX RECEIVE  
14 13               PX SEND HASH :TQ10002
15 14                VIEW  
16 15                 WINDOW SORT 
17 16                  PX RECEIVE  
18 17                   PX SEND HASH :TQ10001
19 18                    FILTER  
20 19                     HASH JOIN  
21 20                      PX RECEIVE  
22 21                       PX SEND BROADCAST :TQ10000
23 22                        PX BLOCK ITERATOR 
24 23                         TABLE ACCESS STORAGE FULL RECORDS1
25 20                      PX BLOCK ITERATOR 
26 25                       TABLE ACCESS STORAGE FULL RECORDS2
27 8          VIEW  
28 27           SORT UNIQUE 
29 28            PX RECEIVE  
30 29             PX SEND HASH :TQ10004
31 30              PX BLOCK ITERATOR 
32 31               TABLE ACCESS STORAGE FULL AC_


вопросы:
1) почему в запросе две кляузы group by, а в плане - ТРИ (помечены знаком ++++++++ выше)?

2) есть ли смысл пытаться переписать запрос так, чтобы сначала был джойн всех таблиц, а потом ОДИН group by - это может ускорить запрос при условии, что group by в блоке "with rec as (--обработанные проводки" сейчас уменьшает кол-во строк перед последним джойном в несколько раз?

т.е. вопрос теоретический - что эффективнее обрабатывавает оракл:
а) сначала уменьшить кол-во строк (в N раз) группировкой, потом джойнить результаты
б) сначала джойнить , потом группировать
РДТЕХовцы на курсах высказываются за первый подход, а что говорит ваш опыт, в т.ч. про параметр N?

спасибо!
...
Рейтинг: 0 / 0
group + join или наоборот?
    #39305807
bishnike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexus12,

Стоит ли пытаться проводить оптимизацию не разобравшись в запросе?

Судя по всему вы не замутили что в запросе есть ещё и
Код: sql
1.
sum(...)over(partition by ...) 
...
Рейтинг: 0 / 0
group + join или наоборот?
    #39305811
K790
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexus12,

а что у вас в records_v?
...
Рейтинг: 0 / 0
group + join или наоборот?
    #39305865
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
K790, в records_v джойн двух половин одной логической таблицы: records1 left outer records2
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / group + join или наоборот?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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