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')