{code:SQL | title= Rollup 제거 예제 | borderStyle=solid} select e1.department_id, e1.job_id, e1.avg_sal from (select e.department_id, e.job_id, avg(e.salary) avg_sal from employees e group by rollup(e.department_id, e.job_id)) e1 where e1.job_id = 'MK_REP'; |
============
Plan Table
============
Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
0 | SELECT STATEMENT | 1 | 1 | 00:00:00.01 | 2 | ||||
1 | HASH GROUP BY | 1 | 1 | 00:00:00.01 | 2 | 763K | 763K | 394K (0) | |
2 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 1 | 00:00:00.01 | 2 | |||
| INDEX RANGE SCAN | EMP_JOB_IX | 1 | 1 | 00:00:00.01 | 1 |
Predicate Information (identified by operation id):
3 - access("E"."JOB_ID"='MK_REP')
* Plan상에서 Rollup이 사라졌다. Transformer가 SQL을 아래처럼 바꿈 |
| {code:SQL|title= SQL변환 |borderStyle=solid}
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
where e.job_id = 'MK_REP'
group by e.department_id, e.job_id;
============
Plan Table
============
-----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1 |00:00:00.01 | 2 | | | |
| 1 | HASH GROUP BY | | 1 | 1 |00:00:00.01 | 2 | 763K| 763K| 394K (0)|
| 2 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 1 |00:00:00.01 | 2 | | | |
|* 3 | INDEX RANGE SCAN | EMP_JOB_IX | 1 | 1 |00:00:00.01 | 1 | | | |
-----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."JOB_ID"='MK_REP')
{code:SQL | title= Rollup 미제거 예제 | borderStyle=solid} select e1.department_id, e1.job_id, e1.avg_sal from (select e.department_id, e.job_id, avg(e.salary) avg_sal from employees e group by rollup(e.department_id, e.job_id)) e1 where e1.department_id = 12000; |
============
Plan Table
============
Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
0 | SELECT STATEMENT | 1 | 0 | 00:00:00.01 | 1 | ||||
1 | VIEW | 1 | 0 | 00:00:00.01 | 1 | ||||
2 | SORT GROUP BY ROLLUP | 1 | 0 | 00:00:00.01 | 1 | 1024 | 1024 | ||
3 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 0 | 00:00:00.01 | 1 | |||
| INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 1 | 0 | 00:00:00.01 | 1 |
Predicate Information (identified by operation id):
4 - access("E"."DEPARTMENT_ID"=12000)
* 이러한 현상이 나타나는 이유 Rollup을 논리적으로 풀어볼 경우 확실하게 알 수 있다.
{code:SQL|title= Rollup 비교 |borderStyle=solid}
--변환전
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
group by rollup(e.department_id, e.job_id);
--변환후
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
group by e.department_id, e.job_id
union all
select e.department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
group by e.department_id
union all
select NULL department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
group by null
-- 상수조건을 주면
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
where e.job_id = 'MK_REP'
group by e.department_id, e.job_id
union all
select e.department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
where NULL = 'MK_REP' -- Null 비교는 항상 False이므로
group by e.department_id
union all
select NULL department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
where NULL = 'MK_REP' -- Null 비교는 항상 False이므로
group by null ;
|
Cube 가장 오른쪽의 컬럼이 인라인뷰 외부에서 동등조건으로 사용되었을 때 동일한 원리로 Cube삭제되고 레벨이 낮은 Rollup으로 변경되는 것을 살펴볼 수 있다.
Cube 예제
select e1.department_id, e1.job_id, e1.avg_sal
from (select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
group by cube(e.department_id, e.job_id)) e1
where e1.job_id = 'MK_REP';
============
Plan Table
============
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 |00:00:00.01 | 2 | | | |
| 1 | VIEW | | 1 | 2 |00:00:00.01 | 2 | | | |
| 2 | SORT GROUP BY ROLLUP | | 1 | 2 |00:00:00.01 | 2 | 2048 | 2048 | 2048 (0)|
| 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 1 |00:00:00.01 | 2 | | | |
|* 4 | INDEX RANGE SCAN | EMP_JOB_IX | 1 | 1 |00:00:00.01 | 1 | | | |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("E"."JOB_ID"='MK_REP')
큐브 비교
-- 변환전
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
group by cube(e.department_id, e.job_id);
-- 변환후
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
group by e.department_id, e.job_id
union all
select NULL department_id, e.job_id, avg(e.salary) avg_sal
from employees e
group by e.job_id
union all
select e.department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
group by e.department_id
union all
select NULL department_id, NULL job_id, avg(e.salary) avg_sal
from employees e;
-- 상수조건을 주면
select e.department_id, e.job_id, avg(e.salary) avg_sal
from employees e
where e.job_id = 'MK_REP'
group by e.department_id, e.job_id
union all
select NULL department_id, e.job_id, avg(e.salary) avg_sal
from employees e
where e.job_id = 'MK_REP'
group by e.job_id
union all
select e.department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
where NULL = 'MK_REP' -- Null 비교는 항상 False이므로
group by e.department_id
union all
select NULL department_id, NULL job_id, avg(e.salary) avg_sal
from employees e
where NULL = 'MK_REP' -- Null 비교는 항상 False이므로
group by null;
결론
Rollup이나 Cube에서 선언된 맨 오른쪽 컬럼 인라인뷰 바깥에서 동등조건으로 사용되었을때
Rollup은 Group By가 되고 Cube는 Rollup이 된다.