Oracle/Administration2019. 8. 22. 16:50

19.1 버전부터 Hybrid Partitioned 테이블을 생성할 수 있다.


테스트를 위해 아래와 같이 텍스트 파일을 생성하자.

-- 1
C:\>type C:\app\ora19c\admin\ora19c\ext1\205001.txt
1,20500101
2,20500102

C:\>type C:\app\ora19c\admin\ora19c\ext2\205002_01.txt
3,20500201

C:\>type C:\app\ora19c\admin\ora19c\ext2\205002_02.txt
4,20500202

SYS 유저로 접속한 세션에서 아래와 같이 디렉터리를 생성하고, TUNA 유저에 전체 권한을 부여하자.

-- 2
CREATE OR REPLACE DIRECTORY dir_ext1 AS 'C:\app\ora19c\admin\ora19c\ext1';
CREATE OR REPLACE DIRECTORY dir_ext2 AS 'C:\app\ora19c\admin\ora19c\ext2';

GRANT ALL ON DIRECTORY dir_ext1 TO tuna;
GRANT ALL ON DIRECTORY dir_ext2 TO tuna;

아래의 구문으로 Hybrid Partitioned 테이블을 생성할 수 있다. p1, p2 파티션은 외부 파일, p3 파티션은 파티션 세그먼트를 조회한다. ORACLE_LOADER 외에도 ORACLE_DATAPUMP, ORACLE_HDFS, ORACLE_HIVE 등의 유형을 사용할 수 있다.

-- 3
DROP TABLE t1 PURGE;

CREATE TABLE t1 (c1 NUMBER, c2 DATE)
EXTERNAL PARTITION ATTRIBUTES (
    TYPE ORACLE_LOADER
    DEFAULT DIRECTORY dir_ext1
    ACCESS PARAMETERS (
        RECORDS DELIMITED BY NEWLINE
        NOBADFILE NOLOGFILE NODISCARDFILE
        FIELDS TERMINATED BY ','
        OPTIONALLY ENCLOSED BY '"'
        MISSING FIELD VALUES ARE NULL (
            c1
          , c2 CHAR(8) DATE_FORMAT DATE MASK "YYYYMMDD"
        )
    )
)
PARTITION BY RANGE (c2) (
    PARTITION p1 VALUES LESS THAN (DATE '2050-02-01') EXTERNAL LOCATION ('205001.txt')
  , PARTITION p2 VALUES LESS THAN (DATE '2050-03-01') EXTERNAL DEFAULT DIRECTORY dir_ext2
                                                               LOCATION ('205002_01.txt', '205002_02.txt')
  , PARTITION p3 VALUES LESS THAN (MAXVALUE)
);

external 파티션에 DML 작업을 수행하면 에러가 발생한다. internal 파티션은 DML 작업을 수행할 수 있다.

-- 4
INSERT INTO t1 VALUES (7, DATE '2050-02-03');

ORA-14466: 읽기 전용 분할 영역이나 하위 분할 영역의 데이터는 수정할 수 없습니다.

INSERT INTO t1 VALUES (5, DATE '2050-03-01');
INSERT INTO t1 VALUES (6, DATE '2050-03-02');
COMMIT;

아래는 t1 테이블을 조회한 결과다. 5-2번 쿼리에서 파티션 Pruning이 동작하는 것을 확인할 수 있다.

-- 5-1
SELECT * FROM t1;

C1 C2
-- -------------------
 1 2050-01-01 00:00:00
 2 2050-01-02 00:00:00
 3 2050-02-01 00:00:00
 4 2050-02-02 00:00:00
 5 2050-03-01 00:00:00
 6 2050-03-02 00:00:00

6 행이 선택되었습니다.

---------------------------------------------------------------
| Id  | Operation                      | Name | Pstart| Pstop |
---------------------------------------------------------------
|   0 | SELECT STATEMENT               |      |       |       |
|   1 |  PARTITION RANGE ALL           |      |     1 |     3 |
|   2 |   TABLE ACCESS HYBRID PART FULL| T1   |     1 |     3 |
|   3 |    TABLE ACCESS FULL           | T1   |     1 |     3 |
---------------------------------------------------------------

-- 5-2
SELECT * FROM t1 WHERE c2 = DATE '2050-02-01';

C1 C2
-- -------------------
 3 2050-02-01 00:00:00

1개의 행이 선택되었습니다.

-------------------------------------------------------
| Id  | Operation              | Name | Pstart| Pstop |
-------------------------------------------------------
|   0 | SELECT STATEMENT       |      |       |       |
|   1 |  PARTITION RANGE SINGLE|      |     2 |     2 |
|*  2 |   TABLE ACCESS FULL    | T1   |     2 |     2 |
-------------------------------------------------------

DBMS_STATS.GATHER_TABLE_STATS 프로시저로 테이블의 통계정보를 수집할 수 있다.

-- 6
EXEC DBMS_STATS.GATHER_TABLE_STATS ('TUNA', 'T1');

SELECT table_name, partition_name, object_type, num_rows
  FROM user_tab_statistics
 WHERE table_name = 'T1';

TABLE_NAME PARTITION_NAME OBJECT_TYPE NUM_ROWS
---------- -------------- ----------- --------
T1                        TABLE              6
T1         P1             PARTITION          2
T1         P2             PARTITION          2
T1         P3             PARTITION          2

4 행이 선택되었습니다.

인덱스는 PARTIAL NON-UNIQUE 인덱스만 생성할 수 있다.

-- 7
CREATE INDEX t1_x1 ON t1 (c2) LOCAL;

ORA-14354: 하이브리드 분할 테이블에 대해 지원되지 않는 작업입니다.

CREATE INDEX t1_x1 ON t1 (c2) LOCAL INDEXING PARTIAL;

인덱스가 생성되었습니다.

아래는 INDEX 힌트를 사용한 쿼리다. 8-2번 쿼리는 에러가 발생한다. PARTIAL 인덱스가 생성되지 않은 파티션에 INDEX 힌트를 사용했기 때문이다.

-- 8-1
SELECT /*+ INDEX(T1) */ * FROM t1 WHERE c2 = DATE '2050-03-01';

C1 C2
-- -------------------
 5 2050-03-01 00:00:00

1개의 행이 선택되었습니다.

----------------------------------------------------------------------------
| Id  | Operation                                  | Name  | Pstart| Pstop |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT                           |       |       |       |
|   1 |  PARTITION RANGE SINGLE                    |       |     3 |     3 |
|   2 |   TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T1    |     3 |     3 |
|*  3 |    INDEX RANGE SCAN                        | T1_X1 |     3 |     3 |
----------------------------------------------------------------------------

-- 8-2
SELECT /*+ INDEX(T1) */ * FROM t1 WHERE c2 = DATE '2050-02-01';

ORA-01502: 인덱스 'TUNA.T1_X1'또는 인덱스 분할영역은 사용할 수 없은 상태입니다

아래는 인덱스 생성 시점의 통계정보다.

-- 9
SELECT index_name, partition_name, object_type, num_rows
  FROM user_ind_statistics
 WHERE index_name = 'T1_X1';

INDEX_NAME PARTITION_NAME OBJECT_TYPE NUM_ROWS
---------- -------------- ----------- --------
T1_X1                     INDEX              2
T1_X1      P1             PARTITION          0
T1_X1      P2             PARTITION          0
T1_X1      P3             PARTITION          2

4 행이 선택되었습니다.

아래처럼 데이터를 입력하자.

-- 10
INSERT INTO t1 VALUES (7, DATE '2050-04-01');
INSERT INTO t1 VALUES (8, DATE '2050-04-02');
COMMIT;

테이블 통계정보를 수집하면 에러가 발생한다. 버그로 판단된다. CASCADE 파라미터를 FALSE로 설정해야 테이블 통계정보를 수집할 수 있다.

-- 11
EXEC DBMS_STATS.GATHER_TABLE_STATS ('TUNA', 'T1');

ORA-00600: 내부 오류 코드, 인수: [25027], [0], [0], [0], [0], [0], [1], [1], [], [], [], []

EXEC DBMS_STATS.GATHER_TABLE_STATS ('TUNA', 'T1', CASCADE => FALSE);

PL/SQL 처리가 정상적으로 완료되었습니다.

인덱스는 파티션을 지정해도 에러가 발생한다.

-- 12
EXEC DBMS_STATS.GATHER_INDEX_STATS ('TUNA', 'T1_X1');

ORA-00600: 내부 오류 코드, 인수: [25027], [0], [0], [0], [0], [0], [1], [1], [], [], [], []

EXEC DBMS_STATS.GATHER_INDEX_STATS ('TUNA', 'T1_X1', 'P3');

ORA-00600: 내부 오류 코드, 인수: [25027], [0], [0], [0], [0], [0], [1], [1], [], [], [], []

차선책으로 인덱스 REBUILD를 통해 통계정보를 갱신할 수 있습니다.

-- 13
ALTER INDEX t1_x1 REBUILD PARTITION p3 PARALLEL 2 ONLINE;

인덱스가 변경되었습니다.

SELECT index_name, partition_name, object_type, num_rows
  FROM user_ind_statistics
 WHERE index_name = 'T1_X1';

INDEX_NAME PARTITION_NAME OBJECT_TYPE NUM_ROWS
---------- -------------- ----------- --------
T1_X1                     INDEX              4
T1_X1      P1             PARTITION          0
T1_X1      P2             PARTITION          0
T1_X1      P3             PARTITION          4

4 행이 선택되었습니다.


'Oracle > Administration' 카테고리의 다른 글

ALTER SEQUENCE RESTART  (0) 2019.09.04
DBA_LOGSTDBY_NOT_UNIQUE  (0) 2019.08.27
Partitioned External 테이블  (0) 2019.08.22
인덱스 명명 규칙  (0) 2019.08.19
파티션 통계정보 복사  (0) 2019.07.26
Posted by 정희락_