{code:SQL | title= Grouping Sets예제 | borderStyle=solid} select e.department_id, e.job_id, avg(e.salary) avg_sal from employees e group by grouping sets(e.department_id, e.job_id); |
============
Plan Table
============
Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem |
0 | SELECT STATEMENT | 1 | 31 | 00:00:00.01 | 46 | 3 | 3 | ||||
1 | TEMP TABLE TRANSFORMATION | 1 | 31 | 00:00:00.01 | 46 | 3 | 3 | ||||
2 | LOAD AS SELECT | 1 | 0 | 00:00:00.01 | 11 | 0 | 1 | 264K | 264K | 264K (0) | |
3 | TABLE ACCESS FULL | EMPLOYEES | 1 | 107 | 00:00:00.01 | 7 | 0 | 0 | |||
4 | LOAD AS SELECT | 1 | 0 | 00:00:00.01 | 10 | 1 | 1 | 264K | 264K | 264K (0) | |
5 | HASH GROUP BY | 1 | 19 | 00:00:00.01 | 6 | 1 | 0 | 763K | 763K | 1276K (0) | |
6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6644_4BB8158F | 1 | 107 | 00:00:00.01 | 6 | 1 | 0 | |||
7 | LOAD AS SELECT | 1 | 0 | 00:00:00.01 | 8 | 0 | 1 | 264K | 264K | 264K (0) | |
8 | HASH GROUP BY | 1 | 12 | 00:00:00.01 | 3 | 0 | 0 | 776K | 776K | 906K (0) | |
9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6644_4BB8158F | 1 | 107 | 00:00:00.01 | 3 | 0 | 0 | |||
10 | VIEW | 1 | 31 | 00:00:00.01 | 8 | 2 | 0 | ||||
11 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6645_4BB8158F | 1 | 31 | 00:00:00.01 | 8 | 2 | 0 |
1 - SEL$658826F8
2 - SEL$375F4E67
3 - SEL$375F4E67 / SYS_TBL_$1$@SEL$375F4E67
4 - SEL$6210AD40
6 - SEL$6210AD40 / SYS_TEMP_0FD9D6649_4BB8158F@SEL$6210AD40
7 - SEL$F3EE7E8E
9 - SEL$F3EE7E8E / SYS_TEMP_0FD9D6649_4BB8158F@SEL$F3EE7E8E
10 - SEL$B441CC55 / sys_view_v@SEL$658826F8
11 - SEL$B441CC55 / SYS_TEMP_0FD9D664A_4BB8158F@SEL$658826FA
* 테이블을 임시테이블로 변환하고 세번 반복사용하였다 |
| Grouping Sets의 논리적으로 풀어낸 SQL은 다음과 같다
{code:SQL|title= SQL변환 |borderStyle=solid}
with
temp0 as
(select /*+ materialize */ department_id c0, job_id c1, salary a0
from employees) ,
temp1 as
(select /*+ materialize */ NULL c0, c1, count(a0) a1, sum(a0) a0
from temp0
group by c1 ) ,
temp2 as
(select /*+ materialize */ c0, NULL c1, count(a0) a1, sum(a0) a0
from temp0
group by c0) ,
temp3 as
(select temp1.* from temp1
union all
select temp2.* from temp2 )
select c0 department_id, c1 job_id, a0 avg_sal
from (select c0, c1, decode(a0, 0, to_number(null), a1/a0) a0
from temp3 );
|
실제 10053트레이스 결과에서도 위에서 풀어낸 SQL과 동일한 쿼리블록으로 변환된 것을 확인할 수 있다. {code:SQL | title= 10053 체크 | borderStyle=solid} – temp0 Copy query block qb# -1 (<unnamed>) : SELECT "SYS_TBL_$1$"."DEPARTMENT_ID", "SYS_TBL_$1$"."JOB_ID", "SYS_TBL_$1$"."SALARY" FROM "HR"."EMPLOYEES" "SYS_TBL_$1$" Registered qb: SEL$375F4E67 0xd98bd64 (PARSER) – temp1 Copy query block qb# -1 (<unnamed>) : SELECT /*+ */ NULL C0, C1 C1, BIN_TO_NUM(1, GROUPING(C1)) D0, COUNT(A0), SUM(A0) FROM "SYS"."SYS_TEMP_0FD9D6649_4BB8158F" GROUP BY (C1) Registered qb: SEL$6210AD40 0xd989668 (PARSER) – temp2 Copy query block qb# -1 (<unnamed>) : SELECT /*+ */ C0 C0, NULL C1, BIN_TO_NUM(GROUPING(C0), 1) D0, COUNT(A0), SUM(A0) FROM "SYS"."SYS_TEMP_0FD9D6649_4BB8158F" GROUP BY (C0) Registered qb: SEL$F3EE7E8E 0xd985d14 (PARSER) {code} |
개선점
이왕 적재를 하려면 부피를 줄여서 적재하면 효율적일텐데 Oracle Transformer는 Grouping없이 적재를 하여
성능저하가 나타날 수 있다.
이럴 경우 직접 SQL을 수정하여 튜닝하여 적재량을 줄인 후 제공하는 방법이 필요함