Oracle 21c에 Hash Rollup 기능이 추가되었습니다. 이 기능은 ROLLUP에 대해 해시 방식의 집계를 사용으로써 성능을 개선합니다.
테스트를 위해 아래와 같이 테이블을 생성하겠습니다.
-- 1
DROP TABLE t1 PURGE;
CREATE TABLE t1 (c1, c2) AS SELECT CEIL (ROWNUM / 10000), LPAD ('X', 100, 'X') FROM XMLTABLE ('1 to 10000000');
아래는 19.3 버전에서 ROLLUP을 사용한 쿼리의 실행 계획입니다. 수행에 2.51초가 소요되고, 실행 계획 2번에 SORT GROUP BY ROLLUP 오퍼레이션이 표시됩니다.
-- 2: 19.3
SELECT c1, COUNT (*) FROM t1 GROUP BY ROLLUP (c1);
-----------------------------------------------------------------------------------------
| Id | Operation | Name | A-Rows | A-Time | Buffers | Reads | Used-Mem |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1001 |00:00:02.51 | 153K| 153K| |
| 1 | SORT GROUP BY ROLLUP| | 1001 |00:00:02.51 | 153K| 153K|51200 (0)|
| 2 | TABLE ACCESS FULL | T1 | 10M|00:00:01.43 | 153K| 153K| |
-----------------------------------------------------------------------------------------
아래는 21.3 버전에서 ROLLUP을 사용한 쿼리의 실행 계획입니다. 수행에 0.84초가 소요되고, 실행 계획 2번에 HASH GROUP BY ROLLUP 오퍼레이션이 표시됩니다. 아울러 Outline Data 항목에 USE_HASH_AGGREGATION(@"SEL$1" ROLLUP) 힌트가 표시되고, Column Projection Information 항목에서 rowset이 사용된 것을 확인할 수 있습니다.
-- 3: 21.3
SELECT c1, COUNT (*) FROM t1 GROUP BY ROLLUP (c1);
-----------------------------------------------------------------------------------------
| Id | Operation | Name | A-Rows | A-Time | Buffers | Reads | Used-Mem |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1001 |00:00:00.84 | 153K| 153K| |
| 1 | HASH GROUP BY ROLLUP| | 1001 |00:00:00.84 | 153K| 153K| 1494K (0)|
| 2 | TABLE ACCESS FULL | T1 | 10M|00:00:00.48 | 153K| 153K| |
-----------------------------------------------------------------------------------------
Outline Data
-------------
USE_HASH_AGGREGATION(@"SEL$1" ROLLUP)
쿼리에 NO_USE_HASH_AGGREGATION 힌트를 사용하면 19.3 버전과 동일한 실행 계획이 생성됩니다.
-- 4
SELECT /*+ NO_USE_HASH_AGGREGATION */ c1, COUNT (*) FROM t1 GROUP BY ROLLUP (c1);
-----------------------------------------------------------------------------------------
| Id | Operation | Name | A-Rows | A-Time | Buffers | Reads | Used-Mem |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1001 |00:00:02.52 | 153K| 153K| |
| 1 | SORT GROUP BY ROLLUP| | 1001 |00:00:02.52 | 153K| 153K|51200 (0)|
| 2 | TABLE ACCESS FULL | T1 | 10M|00:00:01.47 | 153K| 153K| |
-----------------------------------------------------------------------------------------
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1
---------------------------------------------------------------------------
1 - SEL$1
- NO_USE_HASH_AGGREGATION
참고로 이 기능은 _sqlexec_hash_rollup_enabled 파라미터와 관련이 있습니다.
-- 5
NAME VALUE DEFAULT_VALUE DESCRIPTION
---------------------------- ----- ------------- ------------------
_sqlexec_hash_rollup_enabled TRUE TRUE enable hash rollup
_sqlexec_hash_rollup_enabled 파라미터를 FALSE로 설정하면 앞선 쿼리와 동일한 실행 계획이 생성됩니다.
-- 6
SELECT /*+ OPT_PARAM('_sqlexec_hash_rollup_enabled' 'false') */ c1, COUNT (*) FROM t1 GROUP BY ROLLUP (c1);
-----------------------------------------------------------------------------------------
| Id | Operation | Name | A-Rows | A-Time | Buffers | Reads | Used-Mem |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1001 |00:00:02.51 | 153K| 153K| |
| 1 | SORT GROUP BY ROLLUP| | 1001 |00:00:02.51 | 153K| 153K|51200 (0)|
| 2 | TABLE ACCESS FULL | T1 | 10M|00:00:01.46 | 153K| 153K| |
-----------------------------------------------------------------------------------------
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1
---------------------------------------------------------------------------
0 - STATEMENT
- OPT_PARAM('_sqlexec_hash_rollup_enabled' 'false')