해시 파티션은 ORA_HASH 함수와 동일한 해시 알고리즘을 사용합니다. ORA_HASH 함수로 해시 파티션에 대한 skewness를 시뮬레이션할 수 있습니다.
테스트를 위해 아래와 같이 테이블을 생성하겠습니다. t1, t2 테이블은 64개의 해시 파티션으로 구성되어 있으며, t1 테이블은 1개, t2 테이블은 2개의 파티션 키로 해시 파티션을 생성합니다.
-- 1 DROP TABLE t1 PURGE; DROP TABLE t2 PURGE; CREATE TABLE t1 (c1) PARTITION BY HASH (c1) PARTITIONS 64 AS SELECT ROWNUM FROM XMLTABLE ('1 to 64'); CREATE TABLE t2 (c1, c2) PARTITION BY HASH (c1, c2) PARTITIONS 64 AS SELECT ROWNUM, ROWNUM FROM XMLTABLE ('1 to 64');
아래 쿼리의 결과에서 TBL$OR$IDX$PART$NUM 함수로 생성한 partition_position과 ORA_HASH 함수로 생성한 hash_value가 동일한 것을 확인할 수 있습니다.
-- 2 SELECT c1 , TBL$OR$IDX$PART$NUM (TUNA.T1, 0, 1, 0, ROWID) AS partition_position , ORA_HASH (c1, 63) + 1 AS hash_value FROM t1 PARTITION FOR (1); C1 PARTITION_POSITION HASH_VALUE -- ------------------ ---------- 1 56 56 15 56 56 25 56 56 38 56 56 4 행이 선택되었습니다.
2개의 파티션 키로 생성한 해시 파티션은 2개의 해시 함수를 사용합니다.
-- 3 SELECT c1, c2 , TBL$OR$IDX$PART$NUM (TUNA.T2, 0, 1, 0, ROWID) AS partition_position , ORA_HASH (c1, 31) + ORA_HASH (c2, 31) + 1 AS hash_value FROM t2 PARTITION FOR (1, 1); C1 C2 PARTITION_POSITION HASH_VALUE -- -- ------------------ ---------- 1 1 47 47 15 15 47 47 25 25 47 47 29 29 47 47 38 38 47 47 5 행이 선택되었습니다.
아래 쿼리로 64개의 해시 파티션에 대한 NDV 별 skewness를 조회할 수 있습니다. 1024가 0.86으로 skewness가 가장 높고, 5120가 0.09로 kewness가 가장 낮습니다. 참고로 SKEWNESS_POP 함수는 Oracle 21c부터 사용할 수 있습니다.
-- 4 SET SERVEROUT ON DECLARE v1 NUMBER; BEGIN FOR i IN 1 .. 8 LOOP SELECT SKEWNESS_POP (CEIL (COUNT (*) / i)) INTO v1 FROM DUAL CONNECT BY LEVEL <= i * 1024 GROUP BY ORA_HASH (LEVEL, 63); DBMS_OUTPUT.PUT_LINE (i * 1024 || ':' || TO_CHAR (v1, '0.999999')); END LOOP; END; / 1024: 0.857664 2048: 0.255452 3072: 0.461798 4096: 0.568748 5120: 0.090917 -- ! 6144: 0.238424 7168: 0.120469 8192: 0.167159 PL/SQL 처리가 정상적으로 완료되었습니다.
아래 쿼리로 파티션 별 NDV의 분포를 조회할 수 있습니다. SKEW가 없다면 NDV가 1024개인 경우 각각의 파티션에 16개(=1024/64)의 값이 저장되어야 합니다.
-- 5 SELECT ORA_HASH (LEVEL, 63) + 1 AS partition_position , CEIL (COUNT (*) / :v1) AS cnt FROM DUAL CONNECT BY LEVEL <= :v1 * 1024 GROUP BY ORA_HASH (LEVEL, 63) ORDER BY partition_position;
아래 차트는 앞선 쿼리의 결과를 보여줍니다.
