Database/Oracle2015. 5. 11. 10:54

방법1)

1. sqlplus를 수행하기 전에 해당 디렉토리에 sql파일(test.sql) 복사

2. sqlplus 접속

3. sql파일 수행

 SQL>@test.sql



방법2)

1. sqlplus 접속

2. sql파일 수행 - 절대경로이용

 SQL>@C:\Users\User\test.sql


Posted by 아로나
Database/Oracle2015. 1. 24. 13:32

1. 해당 쿼리를 monitor 힌트를 이용해서 수행

SELECT /* monitor */

ENAME, DEPTNO

FROM EMP

WHERE DEPTNO = ( SELECT DEPTNO FROM EMP WHERE ENAME = 'SCOTT' ) 

AND ENAME != 'SCOTT';


2. 수행한 쿼리의 sql_id 확인

SELECT *

FROM gv$sql_monitor

where SQL_TEXT LIKE '%monitor%';

--SQL_ID : 4nwj4w9ujvv5x


3. sqlplus 직접 로그인

> sqlplus test/test

SQL*Plus: Release 11.2.0.1.0 Production on 토 1월 24 13:28:08 2015

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options


4. sqlplus 레이아웃 조정 및 플랜쿼리 수행

SQL> set long 99999

SQL> set longc 200

SQL> set lines 200

SQL> set pages 9999

SQL> select dbms_sqltune.report_sql_monitor(sql_id => '4nwj4w9ujvv5x', report_level=>'ALL',

  2  type=>'TEXT') as text from dual;


5. 결과 확인

SQL> select dbms_sqltune.report_sql_monitor(sql_id => '4nwj4w9ujvv5x', report_level=>'ALL',

  2  type=>'TEXT') as text from dual;


TEXT

--------------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------

SQL Monitoring Report


SQL Text

------------------------------

SELECT /*+ monitor */ ENAME, DEPTNO FROM EMP WHERE DEPTNO = ( SELECT DEPTNO FROM EMP WHERE ENAME = 'SCOTT' ) AND ENAME != 'SCOTT'


Global Information

------------------------------

 Status              :  DONE (ALL ROWS)

 Instance ID         :  1

 Session             :  SCOTT (72:617)

 SQL ID              :  4nwj4w9ujvv5x

 SQL Execution ID    :  16777216

 Execution Started   :  01/24/2015 13:26:15

 First Refresh Time  :  01/24/2015 13:26:15

 Last Refresh Time   :  01/24/2015 13:26:15

 Duration            :  .00046s

 Module/Action       :  Orange for ORACLE DBA/4.0.1 (Build:43)

 Service             :  whisler11g

 Program             :  OrangeMain.exe

 Fetch Calls         :  2


Global Stats

==================================================

| Elapsed |    IO    |  Other   | Fetch | Buffer |

| Time(s) | Waits(s) | Waits(s) | Calls |  Gets  |

==================================================

|    0.00 |     0.00 |     0.00 |     2 |     15 |

==================================================


SQL Plan Monitoring Details (Plan Hash Value=587534197)

==========================================================================================================================

| Id |      Operation       | Name |  Rows   | Cost |   Time    | Start  | Execs |   Rows   | Activity | Activity Detail |

|    |                      |      | (Estim) |      | Active(s) | Active |       | (Actual) |   (%)    |   (# samples)   |

==========================================================================================================================

|  0 | SELECT STATEMENT     |      |         |      |         1 |     +0 |     1 |        4 |          |                 |

|  1 |   TABLE ACCESS FULL  | EMP  |       4 |    3 |         1 |     +0 |     1 |        4 |          |                 |

|  2 |    TABLE ACCESS FULL | EMP  |       1 |    3 |         1 |     +0 |     1 |        1 |          |                 |

==========================================================================================================================



6. 결과 분석 및 쿼리 튜닝

Posted by 아로나
Database/Oracle2015. 1. 24. 12:27

1. data pump용으로 사용할 오라클 디렉토리 확인

SELECT *

FROM DBA_DIRECTORIES;

--DATA_PUMP_DIR E:\oracle11g32bit\admin\oracle11g\dpdump\


2. 해당 디렉토리 의 권한을 import/export할 user에게 부여

GRANT READ, WRITE ON DIRECTORY DATA_PUMP_DIR TO TESTADM;



3.1 EXPDP

 EXPDP TESTADM/TESTADM@ORALCE11G DUMPFILE=TESTADM_150124.DMP DIRECTORY=DATA_PUMP_DIR SCHEMAS=TESTADM JOB_NAME=TESTADM_EXPDP LOGFILE=TESTADM_EXPDP_150124.log


3.2 IMPDP(스키마, 테이블스페이스를 REMAPPING하는 경우)

 IMPDP TESTADM/TESTADM@ORALCE11G DIRECTORY=DATA_PUMP_DIR DUMPFILE=BEFORE_DB_OWNER.DMP REMAP_SCHEMA=BEFORE_DB_OWNER:TESTADM REMAP_TABLESPACE=BEFORE_TS1:AFTER_TS_01,BEFORE_TS2:AFTER_TS_01,BEFORE_TS3:AFTER_TS_01 TRANSFORM:SEGMENT_ATTRIBUTES:N LOGFILE=TESTADM_IMPDP_150124.log

(스키마 BEFORE_DB_OWNER -> TESTADM 으로 변경, 테이블스페이스 BEFORE_TS1,2,3 -> AFTER_TS_01으로 변경)


3.3 IMPDP(일반적인 경우-스키마,테이블스페이스는 변경하지 않는 경우)

 IMPDP TESTADM/TESTADM@ORALCE11G DIRECTORY=DATA_PUMP_DIR dumpfile=TESTADM_150124.DMP



Posted by 아로나
Database/Oracle2015. 1. 24. 11:00

DATAPUMP 기능을 사용하기 위해서는 첫째 DIRECTORY가 설정되어 있어야한다.

 

* 필요 권한 

EXP_FULL_DATABASE

IMP_FULL_DATABASE

 

 

* Directory  조회

 SQL> SELECT * FROM DBA_DIRECTORIES;


 OWNER      DIRECTORY_NAME                 DIRECTORY_PATH
 ---------- ------------------------------ --------------------------------------------------
 SYS        ORACLE_OCM_CONFIG_DIR          /oracle/app/oracle/product/11.2.0/ccr/state
 SYS        DATA_PUMP_DIR                         /oracle/app/oracle/admin/LINUXORCL/dpdump/
 SYS        XMLDIR                                      /oracle/app/oracle/product/11.2.0/rdbms/xml


 

* Directory 생성 및 권한

 SQL> CREATE DIRECTORY DUMP AS '/oracle/dumpfile';

 Directory created.

 SQL> GRANT READ, WRITE ON DIRECTORY DUMP TO SYSTEM;   

 Grant succeeded.

 SQL> GRANT CREATE ANY DIRECTORY TO SYSTEM;

 Grant succeeded.

 SQL>  SELECT * FROM DBA_DIRECTORIES;

 OWNER      DIRECTORY_NAME                 DIRECTORY_PATH
 ---------- ------------------------------ --------------------------------------------------
 SYS        ORACLE_OCM_CONFIG_DIR          /oracle/app/oracle/product/11.2.0/ccr/state
 SYS        DATA_PUMP_DIR                          /oracle/app/oracle/admin/LINUXORCL/dpdump/
 SYS        DUMP                                         /oracle/dumpfile
 SYS        XMLDIR                                      /oracle/app/oracle/product/11.2.0/rdbms/xml

 SQL>

 

 - DUMP = 사용하고자 하는 DIRECTORY 이름지정

 - '/oracle/dumpfile' = DIRECTORY가 사용할 물리적인 경로

 - READ 권한은 Import Pump를 수행하기 위해 필요

 - WRITE 권한은 Export Pump를 수행하기 위해 필요

 - 일반유저로 오브젝트를 생성하기 위해서는 CREATE ANY DIRECTORY 권한을 가지고 있어야 한다.

* Directory 삭제 

 SQL> DROP DIRECTORY DUMP;

 Directory dropped.

 SQL> SELECT * FROM DBA_DIRECTORIES;

 OWNER      DIRECTORY_NAME                 DIRECTORY_PATH
 ---------- ------------------------------ --------------------------------------------------
 SYS        ORACLE_OCM_CONFIG_DIR          /oracle/app/oracle/product/11.2.0/ccr/state
 SYS        DATA_PUMP_DIR                         /oracle/app/oracle/admin/LINUXORCL/dpdump/
 SYS        XMLDIR                                     /oracle/app/oracle/product/11.2.0/rdbms/xml

 SQL>

 

* Default Directory 설정 

 $ export DATA_PUMP_DIR dump

 

* Export

 Full Export

 $ expdp system/oracle dumpfile=full.dmp directory=dump full=y logfile=full.log job_name=fullexp

 

 Metadata Export

 $ expdp system/oracle dumpfile=metadata.dmp directory=dump full=y content=metadata_only logfile=meta.log job_name=meta

 

 Schemas Export

 $ expdp system/oracle dumpfile=test.dmp directory=dump schemas=TEST job_name=test logfile=test.log

 -  expdp 옵션

  * system/oracle - 데이터베이스 유저 및 비밀번호

  * DIRECTORY - 데이터 펌프 파일을 저장하거나 또는 저장되어 있는 디렉토리

  * LOGFILE - 로그가 저장될 파일 이름

  * FULL - 데이터베이스 전체에 데이터 펌프 적용

  * SCHEMAS - 설정된 데이터베이스 유저가 소유한 오브젝트에 대해 데이터 추출

  * TABLES - 명시된 테이블에 대해서만 데이터 추출

  * TABLESPACES - 명시된 테이블스페이스에 저장된 오브젝트에 대해서만 데이터 추출

  * PARALLEL - 데이터 펌프 작업시 병렬 프로세스의 개수를 지정하는 옵션

  * 필터링 옵션

    - EXCLUDE - 데이터 펌프 작업에서 제외될 오브젝트의 종류와 이름을 명시하는 옵션

                        (EXCLUDE=OBJECT_TYPE[:'object_name'],  INCLUDE=TABLE:="TEST"    TEST 테이블만 포함

    - INCLUDE - 데이터 펌프 작업에 포함될 오브젝트의 종류와 이름을 명시하는 옵션

                        (INCLUDE=OBJECT_TYPE[:'object_name'],   

                        EXCLUDE=TABLE:="TEST"     TEST테이블은 제외

                        EXCLUDE=INDEX:\"=EMP%'\"   EMP 테이블의 인덱스 제외

 

    - PARFILE - 지정된 파일에 원하는 옵션을 설정한 후 해당 파일에 설정된 옵션을 적용하여 적제를 수행하는 옵션

 

  * 추출옵션

    - CONTENTS = [ALL | DATA_ONLY | METADATA_ONLY}

   

  * 오브젝트 정의변경 REMAP

    - REMAP_SCHEMA : 적재가 수행되는 데이터베이스에서 오브젝트 소유자를 변경

      (REMAP_SCHEMA='SCOTT' : 'MIKE')  SCOTT유저에서 MIKE유저로 적재

    - REMAP_TABLESPACE : 적재가 수행되는 데이터베이스에서 오브젝트가 저장될 테이블스페이스를 변경

      (REMAP_TABLESPACE='USERS' : 'TOOLS') USER테이블스페이스에서 TOOLS테이블스페이스로 변경

    - REMAP_DATAFILES : 적재가 수행되는 데이터베이스의 테이블스페이스에서 데이터파일의 위치를 변경

      (REMAP_DATAFILE='/data/ts1.dbf' : '/oracle/ts1.dbf') datafile 재정의

      

* Import

 

 Full Import

 $ impdp system/oracle dumpfile=full.dmp directory=dump full=y logfile=fullimp.log job_name=fullimp

 

 Metadata Import (metadata만 export한 파일을 쓸때)

 $ impdp system/oracle dumpfile=metadata.dmp directory=dump full=y sqlfile=metadata.sql logfile=metadata.log

 

 Metadata Import (full export 파일을 쓸때)

 $ impdp system/oracle dumpfile=full.dmp directory=dump full=y content=metadata_only

sqlfile=metadata.sql logfile=metadata.log

 

 Schemas Import

 $ impdp system/oracle dumpfile=full.dmp directory=dump schemas=TEST logfile=test.log job_name=test

 $ impdp system/oracle dumpfile=test.dmp directory=dump full=y logfile=test.log job_name=test

 * 데이터 적재에만 사용되는 옵션 (TABLE_EXITS_ACTION)

  : export/import 기능에서 import의 ignore기능이 datapump에서는 TABLE_EXITS_ACTION 옵션이다.

  SKIP - 동일 이름의 테이블이 존재할 경우 해당 테이블에 대한 데이터 적재 작업 생략

  APPEND - 동일 이름의 테이블이 전재할 경우 데이터를 해당 테이블에 추가로 적재

  REPLACE - 동일 이름의 테이블이 존재할 경우 해당 테이블을 제거한 후 재생성하여 데이터 적재

  TRUNCATE - 동일 이름의 테이블이 존재할 경우 해당 테이블의 데이터를 DELETE한 후 데이터 적재

 

 

ATTACH 옵션

 - ADD_FILE : 추출 파일(DUMPFILE) 추가

 - CONTINUE_CLIENT : 데이터 펌프 작업에 대한 진행 로그 확인

 - EXIT_CLIENT : 데이터 펌프의 클라이언트 관리 세션 종료

 - FILESIZE : ADD_FILE 명령으로 추가되는 파일의 기본 크기 설정

 - KILL_JOB : 데이터 펌프 작업을 삭제 (작업 재시작 불가능)

 - PARALLEL : 병렬 프로세싱 옵션 지정

 - START_JOB : 데이터 펌프 작업 재시작

 - STOP_JOB : 수행중인 데이터 펌프 작업 중단(작업 재시작 가능)


출처 : http://boeok.tistory.com/11

Posted by 아로나
Database/Oracle2014. 11. 26. 21:19

I. 오라클 파티션 정의

1. 파티션 개요
오늘날 기업에서 관리하는 데이터는 수백테라 바이트에 이르는 데이터베이스를 관리한다.
하지만 이런 데이터들 중 몇몇의 Big Transaction Table이 거의 모든 데이터를 가지고 있고 
나머지 테이블들은 이 Big Transaction Table을 경유하여 액세스 하는 용도로 사용된다.

이렇게 데이터 크기도 크고 중요한 Big Transaction Table을 관리하는 부분에서 Troubleshooting이
발생될 경우 데이터베이스의 성능 및 관리작업에 심각한 영향을 받을 수 있다.

이러한 리스크가 있는 Big Transaction Table을 보다 효율적으로 관리하기 위해 Table을
작은 단위로 나눔으로써 데이터 액세스 작업의 성능 향상을 유도하고 데이터 관리를 보다 
수월하게 하고자 하는 개념이다.

 

2. 파티션 테이블의 장점
1) 개선된 가용성 
    - 파티션은 독립적으로 관리된다. 
    - Backup and Restore를 파티션별로 작업할 수 있다. 
    - 같은 테이블에서 Unavailable한 파티션은 다른 파티션에 영향을 주지 않는다. 
2) 관리의 용이성 
    - 사용자가 지정한 값으로 파티션이 가능하다. 
    - 테이블스페이스간에 파티션 이동이 가능하다. 
    - 파티션 레벨에서 Select, Delete, Update가 가능하다. 
3) 개선된 성능 
    - 데이터를 액세스할 때 액세스하는 범위를 줄여 퍼포먼스 향상을 가져올 수 있다. 
    - RAC(Real Application Clusters) 환경에서 인스턴스간 Block Contention을 감소시킨다.

 

 

 

3. 파티션 테이블 사용시 주의할 점
1) 관리적인 관점 
    - 하나의 테이블을 세분화하여 관리하기 때문에 보다 세심한 관리가 요구된다. 
    - 파티션을 잘 못 구성 또는 관리하여 IU(Index Unusable)에 빠지는 것을 주의해야 한다. 
2) 사용하는 관점 
    - 파티션 키로 나누어져 있는 테이블에 파티션 키를 조건으로 주지 않아 전체 파티션을 액세스하지
      않도록 주의해야 한다.

 

 

4. 파티션 테이블의 특징
    - 파티션 테이블은 파티션 키 값에 의해 구성되며, 한 테이블 당 가능한 파티션은 이론적으로 65,535개를
      지원하나 실질적으로는 10,000개까지만 생성 가능하다(Oracle Ver 10.2.0.3 테스트) 


    - 모든 파티션 테이블(또는 인덱스)는 같은 Logical Attribute를 가져야 한다. 
      Ex) Columns, Data Types, Constraints... 


    - 모든 파티션 테이블(또는 인덱스)는 다른 Physical Attribute를 가져야 한다. 
      Ex) PCTFREE, PCTUSED, INITTRANS, MAXTRANS, TABLESPACE, STORAGE... 


    - 파티션 테이블은 'KEY', 'VALUES LESS THAN Literal', 'Physical Attributes'로 구성된다. 


    - 'VALUES LESS THAN Literal' 절에서 'Literal' 값에는 SQL Function을 지원한다. 


    - Composite Column 구성은 16개까지 가능하다.

 

 

II. 파티션 종류

1. Oracle 버전에 따른 파티션
1) Oracle Ver 7.3 
    - Partition View를 처음으로 도입하였다. 
    - 당시 Partition View는 큰 테이블을 동일한 템플릿을 가진 여러 개의 다른 테이블로 분할하고
      UNION ALL을 사용하여 View로 묶은 형태이다. 
    - 그러나 이 방식은 관리의 어려움, 활용성의 부족, 성능등에 대한 이슈로 인하여 Oracle Ver 9i에서는
      더이상 지원하지 않는다.


2) Oracle Ver 8.0 
    - 컬럼 값의 Range 기반으로 된 Range Partition이 최초로 도입되었고, 비로서 Partition의 모습을 갖추었다. 
    - 각 파티션은 각기 다른 테이블 스페이스, Segment에 저장이 가능하다.


3) Oracle Ver 8i 
    - 컬럼 값의 Hash 기반으로 된 hash partition과, Sub Partition을 할 수 있는 Composite Partition이 추가되었다. 
    - 이 당시 Composite Partition은 Range-Hash로만 구성 가능함.


4) Oracle Ver 9i 
    - 리스트 값으로 파티션을 할 수 있는 List Partition이 추가되었다. 
    - Composite Partition에서는 Range-Hash 이외에 Range-List가 추가 지원되었다.


5) Oracle Ver 10g 
    - IOT 파티션이 추가되었다.


6) Oracle Ver 11g 
    - Composite Partition에서 확장된 Extended Composite Partition이 지원된다. 
        -> Range-Range, List-Range, List-Hash, List-List 
    - Reference Partition 추가 
    - Interval Partition 추가 
    - System Partition 추가 
    - Virtual Column Partition 추가

 

2. Partition Table
1) Range Partition 
    - Column Value의 범위를 기준으로 하여 행을 분할하는 형태이다. 
    - Range Partition에서 Table은 단지 논리적인 구조이며 실제 데이터가 물리적으로 저장되는 곳은
      Partition으로 나누어진 Tablespace에 저장이 된다. 
    - PARTITION BY RANGE ( column_list ) : 기본 Table에서 어느 Column을 기준으로 분할할지를 정함.
      VALUES LESS THAN ( value_list )    : 각 Partition이 어떤 값의 범위를 포함 할지 Upper Bound를 정함. 
    - 구문 Sample 
        CREATE TABLE SALES_DATA_2008 
        (
        COLUMN_1 NUMBER        NOT NULL, 
        COLUMN_2 VARCHAR2(4), 
        COLUMN_3 VARCHAR2(4), 
        COLUMN_4 VARCHAR2(2), 
        COLUMN_5 VARCHAR2(2), 
        COLUMN_6 NUMBER 
        ) 
        TABLESPACE TABLE_SPACE_DATA_1
        PCTFREE 5   
        PCTUSED 40
        INITRANS 11
        MAXTRANS 255
        STORAGE 
        ( 
        INITIAL 2048K 
        NEXT 1024K 
        PCTINCREASE 0
        MINEXTENTS 1 
        MAXEXTENTS 121 
        )
        PARTITION BY RANGE ( COLUMN_3, COLUMN_4, COLUMN_5 )
        ( 
        PARTITION P_200801 VALUES LESS THAN ('2008', '04', '01' ),
        PARTITION P_200802 VALUES LESS THAN ('2008', '07', '01' ),
        PARTITION P_200803 VALUES LESS THAN ('2008', '10', '01' ),
        PARTITION P_200804 VALUES LESS THAN ('2009', '01', '01' ),
        PARTITION P_5      VALUES LESS THAN (MAXVALUE)
        TABLESPACE TABLE_SPACE_DATA_2   
        PCTFREE 5
        PCTUSED 40
        INITRANS 11   
        MAXTRANS 255 
        STORAGE 
        (  
        INITIAL 1M 
        NEXT 1M 
        PCTINCREASE 0
        MINEXTENTS 1 
        MAXEXTENTS 121 
        );

 

2) Hash Partition 
    - Partitioning column의 Partitioning Key 값에 Hash 함수를 적용하여 Data를 분할하는 방식.
    - 데이터 이력관리의 목적 보다 성능 향상의 목적으로 나온 개념이다. 
      Hash Partition은 Range Partition에서 범위를 기반으로 나누었을 경우 특정 범위에 분포도가 몰려서
    - 각기 Size가 다르게 되는 것을 보완하여, 일정한 분포를 가진 파티션으로 나누고 균등한 데이터 분포도를
      이용한 병렬처리로 퍼포먼스를 보다 향상시킬 수 있다. 
    - Hash Partition에서 Table은 단지 논리적인 구조이며 실제 데이터가 물리적으로 저장되는 곳은
      Partition으로 나누어진 Tablespace에 저장이 된다. 
    - 구문 Sample 
        CREATE TABLE SALES_DATA_2008 
        (
        COLUMN_1  NUMBER        NOT NULL, 
        COLUMN_2  VARCHAR2(4), 
        COLUMN_3  VARCHAR2(4), 
        COLUMN_4  VARCHAR2(2), 
        COLUMN_5  VARCHAR2(2), 
        COLUMN_6  NUMBER
        ) 
        TABLESPACE TABLE_SPACE_DATA_1
        PCTFREE 5   
        PCTUSED 40
        INITRANS 11
        MAXTRANS 255
        STORAGE 
        ( 
        INITIAL 2048K 
        NEXT 1024K 
        PCTINCREASE 0
        MINEXTENTS 1 
        MAXEXTENTS 121 
        )
        PARTITION BY HASH ( COLUMN_3, COLUMN_4, COLUMN_5 )
        ( 
        PARTITION P_200801,
        PARTITION P_200802,
        PARTITION P_200803,
        PARTITION P_200804,
        PARTITION P_5 VALUES LESS THAN (MAXVALUE)
        )
        );

 

3) Composite(Sub) Partition 
    - 파티션의 컬럼을 Main-Sub 관계로 나누어 분할하는 방식. 
    - Composite Partition이 아닌 다른 파티션에서 물리적인 데이터가 저장되는 곳은 Table이 아닌
      Partition Table에 저장이 되는 것처럼, Composite Partition에서는 Main Partition이 아닌
      Sub Partition에 저장된다. 
    - Composite Partition의 조합 구성은 Oracle의 버전이 올라갈수록 조합하는 방식을 다양하게 지원한다.


      

 
    - 구문 Sample 
        CREATE TABLE SALES_DATA_2008 
        (
        COLUMN_1 NUMBER        NOT NULL, 
        COLUMN_2 VARCHAR2(4), 
        COLUMN_3 VARCHAR2(4), 
        COLUMN_4 VARCHAR2(2), 
        COLUMN_5 VARCHAR2(2), 
        COLUMN_6 NUMBER
        ) 
        TABLESPACE TABLE_SPACE_DATA_1
        PCTFREE 5   
        PCTUSED 40
        INITRANS 11
        MAXTRANS 255
        STORAGE 
        ( 
        INITIAL 2048K 
        NEXT 1024K 
        PCTINCREASE 0
        MINEXTENTS 1 
        MAXEXTENTS 121 
        )
        PARTITION BY RANGE ( COLUMN_3, COLUMN_4  )
        SUBPARTITION BY HASH ( COLUMN_5 )
            (PARTITION P_200801 VALUES LESS THAN ('2008', '04'),
             PARTITION P_200802 VALUES LESS THAN ('2008', '07'),
             PARTITION P_200803 VALUES LESS THAN ('2008', '10')
                 (SUBPARTITIONS  P_200803_S1 TABLESPACE TABLE_SPACE_DATA_1_1,
                  SUBPARTITIONS  P_200803_S2 TABLESPACE TABLE_SPACE_DATA_1_2,
              SUBPARTITIONS  P_200803_S3 TABLESPACE TABLE_SPACE_DATA_1_3,
              SUBPARTITIONS  P_200803_S4 TABLESPACE TABLE_SPACE_DATA_1_4,
              SUBPARTITIONS  P_200803_S5 TABLESPACE TABLE_SPACE_DATA_1_5,
              SUBPARTITIONS  P_200803_S6 TABLESPACE TABLE_SPACE_DATA_1_6,
              SUBPARTITIONS  P_200803_S7 TABLESPACE TABLE_SPACE_DATA_1_7,
              SUBPARTITIONS  P_200803_S8 TABLESPACE TABLE_SPACE_DATA_1_8 
                 ),
             PARTITION P_200804 VALUES LESS THAN ('2009', '01')
            );

 

4) List Partition 
    - Partitioning column의 특정 값으로 분할하는 방식 
    - 데이터 분포도가 낮지 않고, 균등하게 분포되어 있을 때 유용하다. 
    - Composite Partition에서 'Range-List'일 경우 그 효율이 더욱 높아진다. 
    - 다른 파티션 방식처럼 다중 컬럼을 지원하지 않고 단일 컬럼만 가능하다. 
    - 구문 Sample 
        CREATE TABLE SALES_DATA_2008 
        (
        COLUMN_1 NUMBER        NOT NULL, 
        COLUMN_2 VARCHAR2(4), 
        COLUMN_3 VARCHAR2(4), 
        COLUMN_4 VARCHAR2(2), 
        COLUMN_5 VARCHAR2(2), 
        COLUMN_6 NUMBER
        ) 
        TABLESPACE TABLE_SPACE_DATA_1
        PCTFREE 5   
        PCTUSED 40
        INITRANS 11
        MAXTRANS 255
        STORAGE 
        ( 
        INITIAL 2048K 
        NEXT 1024K 
        PCTINCREASE 0
        MINEXTENTS 1 
        MAXEXTENTS 121 
        )
        PARTITION BY LIST(COLUMN_2)
        (
        PARTITION RS VALUES('A') TABLESPACE TABLE_SPACE_DATA_2,
        PARTITION RM VALUES('B') TABLESPACE TABLE_SPACE_DATA_3,
        PARTITION RN VALUES('C') TABLESPACE TABLE_SPACE_DATA_4,
        );

 

5) Reference Partition 
    - Reference Key로 지정된 경우 부모 테이블의 컬럼이 존재하지 않아도 부모의 Partition Key로
      분할하는 방식. 
    - 구문 Sample 
        CREATE TABLE CUSTOMERS
        (
        CUST_ID   NUMBER PRIMARY KEY,
        CUST_NAME VARCHAR2(200),
        RATING    VARCHAR2(1) NOT NULL
        )
        PARTITION BY LIST(RATING)
        (
            PARTITION PA VALUES('A'),
            PARTITION PB VALUES('B')
        );

        -- Detail Table
        CREATE TABLE SALES
        (
        SALES_ID  NUMBER PRIMARY KEY,
        CUST_ID   NUMBER NOT NULL,
        SALES_AMT NUMBER,
        CONSTRAINT FK_SALES_01 FOREIGN KEY (CUST_ID) REFERENCES CUSTOMERS
        )    
        PARTITION BY REFERENCE (FK_SALES_01);
    - 제약조건 
        -> Foreign Key 제약조건이 설정되어 있어야 한다. 
        -> 상속받는 테이블의 Key값이 NOT NULL 이어야 한다. 
    - 테스트 
        -- Normal
        SELECT *
        FROM   SALE_TMP  A,
               CUSTOMERS B
        WHERE  A.CUST_ID = B.CUST_ID
        AND    B.RATING = 'A';
        
        Rows     Row Source Operation
        -------  ------------------------------------
              0  STATEMENT
             28   HASH JOIN  
             28    PARTITION LIST SINGLE PARTITION: 1
             28     TABLE ACCESS FULL CUSTOMERS PARTITION: 1
             56    TABLE ACCESS FULL SALE_TMP 
        
        -- Reference Partition          
        SELECT *
        FROM   SALES     A,
               CUSTOMERS B
        WHERE  A.CUST_ID = B.CUST_ID
        AND    B.RATING = 'A';
        
        Rows     Row Source Operation
        -------  -------------------------------------         
               0  STATEMENT
             28   PARTITION LIST SINGLE PARTITION: 1
             28    HASH JOIN
             28     TABLE ACCESS FULL CUSTOMERS PARTITION: 1
             28     TABLE ACCESS FULL SALES PARTITION: 1

 

6) Interval Partition 
    - Range Partition에서 특정 범위를 지정하고 관리할때는 미리 Range를 만들어주어야 하고
      생성 이후 분할 또는 병합을 할 때는 추가적인 작업을 해주어야 한다. 
    - 하지만 'Interval Partition'에서는 각 파티션을 미리 정의함으로써 파티션 생성을 오라클이 
      직업 해주는 방식이다. 
    - 예제 Sample 
        -- 1. Range Partition 생성     
        CREATE TABLE SALES6
        (
        SALES_ID NUMBER,
        SALES_DT DATE
        )     
        PARTITION BY RANGE(SALES_DT)
        (
            PARTITION P0701 VALUES LESS THAN (TO_DATE('20070201', 'YYYYMMDD')),
            PARTITION P0701 VALUES LESS THAN (TO_DATE('20070301', 'YYYYMMDD'))
        );
        
        -- 2. Partition Key 값의 범위에 없는 값으로 Insert
        INSERT INTO SALES6 VALUES(1, TO_DATE('20070401', 'YYYYMMDD'));
        
        -- Error 
        ORA-14400: inserted partition key does not map to any PARTITION
        
        -- 3. Interval Partition 생성
        CREATE TABLE SALES6
        (
        SALES_ID NUMBER,
        SALES_DT DATE
        )
        PARTITION BY RANGE(SALES_DT) INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
        (
            PARTITION P0701 VALUES LESS THAN(TO_DATE('20080201', 'YYYYMMDD'))
        );
        
        -- 4. Partition Key 값의 범위에 없는 값으로 Insert
        INSERT INTO SALES6 VALUES(1, TO_DATE('20070601', 'YYYYMMDD'));
        
        -- No Error 
        1 row created.

    - 파티션을 특정 테이블 스페이스에 저장하고 싶다면 STORE IN 구문으로 가능하다. 
        -> INTERVAL (NUMTOYMINTERVAL(1, 'MONTH')) STORE IN (TS1, TS2, TS3)
    - 어플리케이션 개발자가 특정 파티션에 접근하고 싶다면 다음의 구문으로 가능하다. 
        -> SELECT * FROM SALES6 PARTITION FOR(TO_DATE('20080501', 'YYYYMMDD'));

 

7) System Partition 
    - 테이블 생성시 파티션 구간을 미리 설정하는 것이 아니라 임의로 나눈 파티션에 대해
      사용자가 원하는 파티션에 데이터를 저장하는 방식. 
    - 이 방식은 사용자가 'System Partition'으로 되어 있는 테이블의 데이터를 DML 하고자 할 때
      직접 파티션을 지정하여 해주어야 한다. 
    - 로컬 인덱스 생성 시, 인덱스도 동일한 방법으로 파티셔닝된다. 
    - 예제 Sample 
        CREATE TABLE SALES3
        (
        SALES_ID     NUMBER,
        PRODUCT_CODE NUMBER,
        STATE_CODE   NUMBER
        )
        PARTITION BY SYSTEM
        (
            PARTITION P1 TABLESPACE USERS,
            PARTITION P2 TABLESPACE USERS
        );
    - Insert 할 때는 반드시 파티션을 지정해 주어야 한다. 
        -- Insert 할 때 테이블의 파티션을 지정하지 않을 경우
        INSERT INTO SALES3 VALUES(1,101,1);
        
        -- Error
        ERROR at line 1:
        ORA-14701: partition-extended name or bind variable must be used for DMLs on
        tables partitioned by the System method
        
        -- Insert을 할 때 테이블의 파티션을 지정한 경우
        insert into sales3 partition (p1) values (1,101,1);
        
        -- No Error
        1 row created.
    - Delete, Update 할 때는 필수는 아니지만 파티션을 지정하지 않을 경우 모든 파티션을
      찾아다녀야 하므로 이 경우에도 가급적 파티션을 지정해 주어야 한다. 
        -> DELETE SALES3 PARTITION(P1) WHERE STATUS_CODE = 1;

 

8) Virtual Column Partition 
    - 파티션으로 나누고자 하는 컬럼이 테이블에서 가공되어 얻을 수 있는 컬럼일 경우
      11g 이전에서는 새로운 컬럼을 추가하고 트리거를 이용하여 컬럼 값을 생성하는 방법을
      사용하여 많은 오버헤드를 감수하였으나, 11g에서는 'Virtual Column Partition'을 
      지원하여 실제로 저장되지 않는 컬럼을 런타임에 계산하여 생성할 수 있다. 또한
      가상 컬럼에 파티션을 적용하는 것도 가능하다. 
    - 예제 Sample 
        -- Virtual Partition 생성
        CREATE TABLE SALES
        (
        SALES_ID NUMBER,
        CUST_ID  NUMBER,
        SALE_CATEGORY VARCHAR2(6)
        GENERATED ALWAYS AS
        (
            CASE WHEN SALES_AMT <= 10000 THEN 'LOW'
                 WHEN SALES_AMT BETWEEN 10000  AND 100000  THEN CASE WHEN CUST_ID < 101       THEN 'LOW'
                                                                     WHEN BETWEEN 101 AND 200 THEN 'MEDIUM'
                                                                     ELSE 'LOW' END
                 WHEN SALES_AMT BETWEEN 100000 AND 1000000 THEN CASE WHEN CUST_ID < 101       THEN 'MEDIUM'
                                                                     WHEN BETWEEN 101 AND 200 THEN 'HIGH'
                                                                     ELSE 'ULTRA' END
                 ELSE 'ULTRA' END
        ) VIRTUAL
        )
        PARTITION BY LIST(SALES_CATEGORY)
        (
            PARTITION P_LOW    VALUES ('LOW'),
            PARTITION P_MEDIUM VALUES ('MEDIUM'),
            PARTITION P_HIGH   VALUES ('HIGH'),
            PARTITION P_ULTRA  VALUES ('ULTRA')
        );
        
        -- Insert 테스트
        INSERT INTO SALES(SALES_ID, CUST_ID, SALES_AMT) VALUES(1, 1, 100);
        
        -- No Error
        1 row created.

 

 

3. Partition Index
1) Local Index 
    - 인덱스를 생성한 인덱스와 파티션된 인덱스가 동일하게 파티션된 형태를 말한다.
    - 인덱스와 테이블은 같은 칼럼에 의해 파티션되며, 하나의 인덱스 파티션이 테이블 
      파티션 하나와 대응되며, 대응되는 인덱스 파티션과 테이블 파티션은 각각 같은 범위를 갖게 된다.
    - 결국 특정한 하나의 인덱스에 포함된 모든 Key들은 하나의 테이블 파티션 내의 데이타만을 가리키게 된다.

 

1-1) Local Prefixed Index 
    - 인덱스의 맨 앞에 있는 컬럼에 의해 파티션되는 방식이다. 
    - Local Prefixed Index에서 컬럼은 Unique/Non-Unique를 모두 허용한다. 
    - Base Table의 파티션이 변경되면 Local Index의 관련 파티션만 변경이 된다. 
        CREATE TABLE DEPT
        (
        DEPTNO NUMBER NOT NULL,
        DNAME  VARCHAR2(10) NOT NULL,
        LOC    VARCHAR2(14)
        )
        PARTITION BY RANGE (DEPTNO)
            (PARTITION PART_1 VALUES LESS THAN (30),
             PARTITION PART_2 VALUES LESS THAN (MAXVALUE)
            );
        
        CREATE INDEX DEPT_N1 on DEPT(DEPTNO) LOCAL;

 

1-2) Local Non-Prefixed Index 
    - Index의 첫번째 column이 Partition Key가 아닌 형태로 Base Table과 동일한 Partition구조를 가진 Index이다.
      (equi-partitioned) 
    - 빠른 access가 요구될 때 유용하다(Base Table의 Partition Key 는 제외...) 
    - Partition단위로 관리할 수 있으므로 Global Index에 비해 운영상 편리하다. 
    - OLAP 측면에서 Global Index보다 조회 속도가 저하된다. 
        CREATE TABLE DEPT
        (
        DEPTNO NUMBER NOT NULL,
        DNAME  VARCHAR2(10) NOT NULL,
        LOC    VARCHAR2(14)
        )
        PARTITION BY RANGE (DEPTNO)
            (PARTITION PART_1 VALUES LESS THAN (30),
             PARTITION PART_2 VALUES LESS THAN (MAXVALUE)
            );

        CREATE INDEX DEPT_N2 on DEPT(LOC) LOCAL;

 

2) Global Index 
    - Global Index는 테이블과 다르게 파티션되는 경우이다.

 

2-1) Global Prefixed Index 
    - Base Table과 비교하여 not equi-partitioned 상태이다. 
    - Oracle은 only Index structure만 관리한다 (Partition은 관리안함) 
    - 최종 Partition에는 Maxvalue값이 반드시 기술되어야 한다. 
    - Local index보다 관리하기 힘들다. 
    - 기준 Table의 Partition이 변경되면 global index의 모든 Partition에 영향을 미친다
      (Global Index 재생성 해야 함) -- 테이블 생성    
        CREATE TABLE SALES_DATA_2008 
        (
            COLUMN_1 NUMBER        NOT NULL, 
            COLUMN_2 VARCHAR2(4), 
            COLUMN_3 VARCHAR2(4), 
            COLUMN_4 VARCHAR2(2), 
            COLUMN_5 VARCHAR2(2), 
            COLUMN_6 NUMBER 
        )  
        PARTITION BY RANGE ( COLUMN_3, COLUMN_4 )
        ( 
            PARTITION P_200801 VALUES LESS THAN ( '04', '01' ),
            PARTITION P_200802 VALUES LESS THAN ( '07', '01' ),
            PARTITION P_200803 VALUES LESS THAN ( '10', '01' ),
            PARTITION P_200804 VALUES LESS THAN ( '12', MAXVALUE ) 
        );
        
        -- Global Prefixed Index 
        CREATE UNIQUE INDEX RANGE2_GPX8 on SALES_DATA_2008( COLUMN_2, COLUMN_1) 
        TABLESPACE TABLE_SPACE_DATA_1 
        PCTFREE    10 
        STORAGE(INITIAL 100K NEXT 100K PCTINCREASE 0  ) 
        GLOBAL PARTITION BY RANGE ( CODE )
        ( 
            PARTITION P_2008_P1 VALUES LESS THAN ('2000'),
            PARTITION P_2008_P2 VALUES LESS THAN ('3000'),
            PARTITION P_2008_P3 VALUES LESS THAN (MAXVALUE)
        );


2-2) Non-Partitioned Index 
    - 파티션과는 아무런 상관없는 Normal Index를 말함.

 


III. 파티션을 사용할 때 알아야 할 사항들

1. 파티션 테이블 및 인덱스 관리를 위한 명령어들
1) 일반 테이블 파티션하기 
    - Export/Import 하는 방법 
        -- 테이블을 Export 한다. 
        exp user/password tables=number file=exp.dmp
        
        -- 백업받은 테이블을 제거한다. 
        drop table numbers;

 

        -- 파티션 테이블을 생성한다. 
        CREATE TABLE NUMBER(QTY NUMBER(3), NAME VARCHAR2(15))
        PARTITION BY RANGE(QTY)
            (PARTITION P1 VALUES LESS THAN (501),
             PARTITION P2 VALUES LESS THAN (MAXVALUE));

        -- ignore=y를 사용하여 데이터를 Import한다. 
       imp user/password tables=number file=exp.dmp ignore=y

    - Subquery를 이용한 방법 
        -- 파티션 테이블을 생성한다. 
        CREATE TABLE PARTBL(QTY NUMBER(3), NAME VARCHAR2(15))
        PARTITION BY RANGE(QTY)
            (PARTITION P1 VALUES LESS THAN(501),
             PARTITION P2 VALUES LESS THAN(MAXVALUE));
        
        -- Subquery를 이용하여 파티션 테이블에 데이터를 입력한다. 
        INSERT INTO PARTBL(QTY, NAME) SELECT * FROM ORIGTBL;
        
        -- Subquery를 이용하여 파티션 테이블에 데이터를 입력한다.

 

    - Partition Exchange 명령어를 사용하는 방법 
        -- ALTER TABLE EXCHANGE PARTITION은 파티션 테이블을 일반 테이블로, 또는 파티션되어
        -- 있지 않은 테이블을 파티션 테이블로 변경시킬 때 사용한다. 
        -- 파티션 테이블 생성
        CREATE TABLE P_EMP (SAL NUMBER(7,2))
        PARTITION BY RANGE(SAL)
            (PARTITION EMP_P1 VALUES LESS THAN (2000),
             PARTITION EMP_P2 VALUES LESS THAN (4000));
        
        -- 첫번째 파티션에 들어갈 데이터
        CREATE TABLE DUMMY_Y 
        SELECT SAL 
        FROM   EMP 
        WHERE  SAL < 2000;
        
        -- 두번째 파티션에 들어갈 데이터
        CREATE TABLE DUMMY_Z
        SELECT SAL
        FROM   EMP 
        WHERE  SAL BETWEEN 2000 AND 3999;
        
        ALTER TABLE P_EMP EXCHANGE PARTITION EMP_P1
        WITH TABLE DUMMY_Y;
        
        ALTER TABLE P_EMP EXCHANGE PARTITION EMP_P2
        WITH TABLE DUMMY_Z;

 

    - 여러 개의 파티션으로 분리된 테이블 중 일부의 파티션만 가진 테이블 생성하기 
        -- 데이타를 Export한 후 필요한 파티션으로 이루어진 테이블을 생성한다. 
        -- 데이터 생성
        CREATE TABLE YEAR(COL1 DATE) PARTITION BY RANGE (COL1)
            (PARTITION OCTOBER  VALUES LESS THAN ('01-NOV-1999) TABLESPACE OCTOBER,
             PARTITION NOVEMBER VALUES LESS THAN ('01-DEC-1999) TABLESPACE NOVEMBER,
             PARTITION DECEMBER VALUES LESS THAN (MAXVALUE)     TABLESPACE DECEMBER);

        -- 데이타를 Import
        IMP USERNAME/PASSWORD FILE=EXPDAT.DMP FROMUSER=<OWNER> TOUSER=<OWNER>
        TABLES=(YEAR:OCTOBER, YEAR:NOVEMBER, YEAR:DECEMBER)
    
    - 파티션을 추가하는 방법 
        -- 파티션 테이블 생성
        CREATE TABLE PART_TBL
            (IN_DATE CHAR(8) PRIMARY KEY,
             EMPNO   NUMBER,
             ENAME   VARCHAR2(20),
             JOB     VARCHAR2(20))
        PARTITION BY RANGE (IN_DATE)
            (PARTITION PART_TBL_03 VALUE LESS THAN ('20000331') TABLESPACE PTS_03,
             PARTITION PART_TBL_04 VALUE LESS THAN ('20000430') TABLESPACE PTS_04,
             PARTITION PART_TBL_05 VALUE LESS THAN ('20000531') TABLESPACE PTS_05,
             PARTITION PART_TBL_06 VALUE LESS THAN ('20000630') TABLESPACE PTS_06,
             PARTITION PART_TBL_07 VALUE LESS THAN ('20000731') TABLESPACE PTS_07,
             PARTITION PART_TBL_08 VALUE LESS THAN ('20000831') TABLESPACE PTS_08,
             PARTITION PART_TBL_09 VALUE LESS THAN ('20000930') TABLESPACE PTS_09,
             PARTITION PART_TBL_10 VALUE LESS THAN ('20001031') TABLESPACE PTS_10);
        
        -- 파티션 추가
        ALTER TABLE PART_TBL ADD PARTITION PART_TBL_11 VALUES LESS THAN ('20001130') TABLESPACE PTS_11;
        ALTER TABLE PART_TBL ADD PARTITION PART_TBL_12 VALUES LESS THAN ('20001231') TABLESPACE PTS_12;
    
    - 특정 파티션을 삭제하는 방법 
        특정 파티션 삭제 이후 삭제한 파티션의 값이 들어올 경우 그 다음 VALUES LESS THAN으로 편입된다. 
        ALTER TABLE PART_TBL DROP PARTITION PART_TBL_08;
    
    - 파티션을 나누는 방법 
        만약 3월만 들어가있는 파티션이 있을 경우, 여기서 1, 2월을 추가하려면 파티션에서 Add가 아닌
        Split을 해 주어야 한다. 
        -- 3월 파티션에서 2월과 3월을 Split함.
        ALTER TABLE PART_TBL SPLIT PARTITION PART_TBL_03 AT ('20000229')
             INTO (PARTITION PART_TBL_02   TABLESPACE PTS_02,
                   PARTITION PART_TBL_03_1 TABLESPACE PTS_03);

       

        -- 2월 파티션에서 1월과 2월을 Split함.
        ALTER TABLE PART_TBL SPLIT PARTITION PART_TBL_02 AT ('20000131')
             INTO (PARTITION PART_TBL_01   TABLESPACE PTS_01,
                   PARTITION PART_TBL_02_1 TABLESPACE PTS_02);

   

    - 파티션 이름을 변경하는 방법 
        ALTER TABLE PART_TBL RENAME PARTITION PART_TBL_02_1 TO PART_TBL_02;

 

    - 파티션의 테이블스페이스를 옮기는 방법 
        ALTER TABLE PART_TBL MOVE PARTITION PART_TBL_10 TABLESPACE PTS_10_1 NOLOGGING;

 

    - 특정 파티션의 데이터를 Truncate 하는 방법 
        Partition의 Data를 모두 삭제하려면 Truncate하는 방법을 사용할 수가 있는데,
        Truncate는 Rollback이 불가능하며 특정 Partition 전체를 삭제하므로 주의하여 사용하여야 한다. 
        ALTER TABLE PART_TBL TRUNCATE PARTITION PART_TBL_02;

 

    - 파티션 테이블의 물리적인 속성 변경하는 방법 
        Partition Table은 특정 Partition의 속성만 변경할 수 있고,
        Table의 속성을 변경하여 전체 Partition에 대해 동일한 변경을 할 수 있다. 

        -- part_tbl의 모든 Partition의 Next 값이 변경
        ALTER TABLE PART_TBL STORAGE (NEXT 10M);

        part_tbl_05 Partition의 Maxextents 값만 변경
        ALTER TABLE PART_TBL MODIFY PARTITION PART_TBL_05 STORAGE (MAXEXTENTS 1000);

 

    - 인덱스 관리 
        파티션 테이블 관련 변경작업을 한 후에는 테이블에 걸려있는 Local, Glocal Index에 대해
        반드시 Rebuild를 해 주어야 한다. -- 특정 파티션의 인덱스 Rebuild
        ALTER INDEX IND_PART_TBL REBUILD PARTITION I_PART_TBL_02;

        -- 글로벌 인덱스 Rebuild
        ALTER INDEX PART_TBL_PK REBUILD;

 

 

2. Backup & Recovery
1) Export 
    - Table-Level Export 
        기존의 Table Export처럼 Table 전체를 Export하는 경우이다.
        이는 Emp Table(Partitioned 또는 Non-Partitioned) 전체를 Export하는 경우이다. 
        $ exp scott/tiger tables=emp file=emp.dmp
    
    - Partition-Level Export 
        이는 Partition Table의 일부 Partition만을 Export하는 것으로,
        Full Mode의 Export시에는 사용하지 못하고, Table단위의 Export시에만 가능하다. 
        ':' 을 이용하여 Partition 이름을 지정하며 이 경우 Emp Table의 px Partition만을 Export
        $ exp scott/tiger tables=emp:px file=emp_par.dmp

 

    - 다음과 같이 두 가지 경우를 Level을 혼용하여 사용하는 것도 가능하다. 
        Sales Table은 전부를, Emp Table에서는 px Partition만을 Export.
        $ exp scott/tiger tables=(emp:px, sales) file=both.dmp

 

2) Import 
    - Table-Level Import 
        Partitioned 또는 Non-Partitioned Table 전체를 Import한다. 
        모든 Import Mode (full, user, table)에서 사용된다. 
        emp table(Partitioned 또는 non-Partitioned) 전체를 Import
        $ imp scott/tiger file=wookpark.dmp tables=emp

 

    - Partition-Level Import 
        Export Dump File에서 (full, user, table중 어떠한 Mode를 이용하여 Export했건간에)
        Partitioned Tabled의 일부 Partition만을 Import한다. 
        Table Import Mode에서만 사용가능하다. 


        -- emp table의 px Partition만을 Import.
        -- ':'을 이용하여 Partition을 지정
        $ imp scott/tiger file=wookpark.dmp tables=emp:px

       

        테이블 단위의 Import시 우선 Table Creation 문장을 수행하고 Row Insert문을 수행하는 것과
        마찬가지로, Partition-level Import도 우선 Partitioned Table의 생성 문장을 수행하고 
        Row Insert문을 수행하게 된다.
        따라서 ignore=y option등을 적절히 사용하면, Non-Partitioned Table과 Partitioned Table간의 변경, 
        Partitioned Table의 구조 변경등을 수행할 수 있게 된다. 
        다음에는 그 중 몇 가지 예이다. 
 
        1. 파티션되어 있지 않은 테이블을 Exp, Imp를 이용하여 파티션 하는 예
        
        1) 파티션되어 있지 않은 테이블을 Export한다.
            $ exp scott/tiger file=wookpark.dmp tables=emp
        
        2) 해당 Table을 Drop한다.
            DROP TABLE EMP
        
        3) 파티션 테이블을 생성한다.
        CREATE TABLE EMP 
        (EMPNO NUMBER(4) NOT NULL,
               ....
        )
        PARTITION BY RANGE (EMPNO),
            (PARTITION EMP1 VALUES LESS THAN (1000) TABLESPACE TS1,
             PARTITION EMP1 VALUES LESS THAN (2000) TABLESPACE TS2,
             PARTITION EMP1 VALUES LESS THAN (3000) TABLESPACE TS3);
        
        4) Import한다.
            $ imp scott/tiger file=wookpark.dmp tables=emp ignore=y
        
        2. Partitioned Table의 Partition들을 exp/imp를 이용하여 Merge하는 예
        1) Merge의 대상이 되는 Partition을 Export한다.
            $exp scott/tiger file=wookpark.dmp tables=emp:emp2
        
        2) Merge의 대상이 되는 Partition을 'alter table...'문장으로 Drop한다.
            ALTER TABLE EMP DROP PARTITION EMP2;
        
        3) Import한다.
            $imp scott/tiger file=wookpark.dmp tables=emp:emp3 ignore=y
        이후 emp Table을 확인하면, emp2 Partition에 있던 Data가 emp3 Partition에 Merge되어 있음을
        확인할 수 있다.

 

3. IU(Index Unusable) 발생 주의
1) IU(Index Unusable)란 파티션이 변경됨으로 인해 파티션 테이블에 있는 인덱스에 영향을 주어
   SELECT나 DML을 시도할 때 오류가 발생되는 것을 말한다.

 

2) IU(Index Unusable)를 발생시키는 Case 
    - Direct path Load의 경우 
        Direct path SQL*Loader 수행 후 인덱스가 테이블의 해당 데이터보다 이전 것이면,
        Unusable 상태가 된다 (Oracle7에서는 인덱스가 Direct Load State가 되었다고 표현한다).
        인덱스가 테이블의 데이터보다 이전 상태라는 것은 데이터를 Load한 후 인덱스를 생성하는 중에 
        Space 부족 등의 원인으로 오류가 발생하였거나, SKIP_INDEX_MAINTENANCE Option을 사용한 경우이다.

    - ROWID가 변경되는 경우 
        ALTER TABLE MOVE PARTITION과 같이 ROWID를 변화시키는 작업은 영향받는 Local Index와
        전체 Global Index를 Unusable 상태가 되게 한다.

    - ROWID를 지우는 작업 
        ALTER TABLE TRUNCATE PARTITION이나 DROP PARTITION과 같이 테이블의 Row를 지우는 경우
        영향받는 Local Index Partition과 모든 Global Index Partition을 Unusable 상태로 만든다.

    - 테이블 Partition 정의를 변경하는 경우 
        ALTER TABLE SPLIT PARTITION은 Local Index의 Partition Definition은 변경시키지만,
        자동으로 인덱스를 새로운 Definition에 맞게 Rebuild하지 않기 때문에 영향받는 
        Local Index Partition을 Unusable 상태로 만든다. 
        또한 이것은 ROWID를 변경시키기 때문에 모든 Global Index Partition을 Unusable 상태로 만든다.

    - 인덱스 Partition 정의를 변경하는 경우 
        ALTER INDEX SPLIT PARTITION은 Index의 Definition은 변경시키지만,
        영향받은 Partition은 Rebuild시키지 않는다. 
        이 작업은 영향받는 인덱스 파티션 부분을 Unusable 상태로 만든다. 
        그러나 Global Index의 경우는 그대로 Usable 상태로 된다.

 

3) 결과적으로 IU 상태가 되면 다음과 같이 조치해야 한다. 
    - Partition Index : Rebuild 
    - Non-Partition Index : Drop and Recreate

 

 

IV. 일반 테이블과 파티션 테이블 테스트
0. 기초 데이터 만들기
1) 일반 테이블

 

① 테이블
CREATE TABLE APPS.NORMAL_TEST_TAB
(
MON_P1 DATE,
GRP_P2 NUMBER,
CNT_N1 NUMBER
);

 

② 샘플 데이터 넣기
INSERT INTO APPS.NORMAL_TEST_TAB
SELECT ADD_MONTHS(TO_DATE('200001', 'YYYYMM'), 
                  DECODE(MOD(LEVEL, 10000), 
                         0, 
                         TRUNC(LEVEL / 10000), 
                         TRUNC(LEVEL / 10000) + 1) - 1) MON_P1,
       DECODE(MOD(LEVEL, 100), 
              0, 
              TRUNC(LEVEL / 100), 
              TRUNC(LEVEL / 100) + 1) * 100 GRP_P2,
       LEVEL CNT_N1
FROM   DUAL
CONNECT BY LEVEL <= 1000000
;

COMMIT;

 

③ 통계정보
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('APPS',
                                'NORMAL_TEST_TAB',
                                CASCADE => TRUE);
END;
/

NORMAL_TEST_TAB
---------------
Rows=997,141                            Blocks=3,032
Empty Blocks=0                          Avg Space=0
Chain Count=0                           Avg Row Length=16
Avg Space Freelist Blocks=0             Freelist Blocks=0
Sample Size=54,167                      Last Analyze=2008/08/24
Partitioned=NO                         

  Column Name                      Nullable Column Type     Distinct    Buckets
  -------------------------------- -------- ------------- ---------- ----------
  MON_P1                                    DATE                 101          1
  GRP_P2                                    NUMBER             9,999          1
  CNT_N1                                    NUMBER           997,141          1

  INDEX
  -----------------------------------------------------------------------------

2) 파티션 테이블

 

① 테이블
CREATE TABLE APPS.PARTITION_TEST_TAB
(
MON_P1 DATE,
GRP_P2 NUMBER,
CNT_N1 NUMBER
)
PARTITION BY RANGE  ( MON_P1 )                                                
SUBPARTITION BY HASH( GRP_P2 )     
(
PARTITION P200001 VALUES LESS THAN(TO_DATE('200001', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200002 VALUES LESS THAN(TO_DATE('200002', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200003 VALUES LESS THAN(TO_DATE('200003', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200004 VALUES LESS THAN(TO_DATE('200004', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200005 VALUES LESS THAN(TO_DATE('200005', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200006 VALUES LESS THAN(TO_DATE('200006', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200007 VALUES LESS THAN(TO_DATE('200007', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200008 VALUES LESS THAN(TO_DATE('200008', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200009 VALUES LESS THAN(TO_DATE('200009', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200010 VALUES LESS THAN(TO_DATE('200010', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200011 VALUES LESS THAN(TO_DATE('200011', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200012 VALUES LESS THAN(TO_DATE('200012', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200101 VALUES LESS THAN(TO_DATE('200101', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200102 VALUES LESS THAN(TO_DATE('200102', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200103 VALUES LESS THAN(TO_DATE('200103', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200104 VALUES LESS THAN(TO_DATE('200104', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200105 VALUES LESS THAN(TO_DATE('200105', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200106 VALUES LESS THAN(TO_DATE('200106', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200107 VALUES LESS THAN(TO_DATE('200107', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200108 VALUES LESS THAN(TO_DATE('200108', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200109 VALUES LESS THAN(TO_DATE('200109', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200110 VALUES LESS THAN(TO_DATE('200110', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200111 VALUES LESS THAN(TO_DATE('200111', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200112 VALUES LESS THAN(TO_DATE('200112', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200201 VALUES LESS THAN(TO_DATE('200201', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200202 VALUES LESS THAN(TO_DATE('200202', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200203 VALUES LESS THAN(TO_DATE('200203', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200204 VALUES LESS THAN(TO_DATE('200204', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200205 VALUES LESS THAN(TO_DATE('200205', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200206 VALUES LESS THAN(TO_DATE('200206', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200207 VALUES LESS THAN(TO_DATE('200207', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200208 VALUES LESS THAN(TO_DATE('200208', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200209 VALUES LESS THAN(TO_DATE('200209', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200210 VALUES LESS THAN(TO_DATE('200210', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200211 VALUES LESS THAN(TO_DATE('200211', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200212 VALUES LESS THAN(TO_DATE('200212', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200301 VALUES LESS THAN(TO_DATE('200301', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200302 VALUES LESS THAN(TO_DATE('200302', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200303 VALUES LESS THAN(TO_DATE('200303', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200304 VALUES LESS THAN(TO_DATE('200304', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200305 VALUES LESS THAN(TO_DATE('200305', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200306 VALUES LESS THAN(TO_DATE('200306', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200307 VALUES LESS THAN(TO_DATE('200307', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200308 VALUES LESS THAN(TO_DATE('200308', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200309 VALUES LESS THAN(TO_DATE('200309', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200310 VALUES LESS THAN(TO_DATE('200310', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200311 VALUES LESS THAN(TO_DATE('200311', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200312 VALUES LESS THAN(TO_DATE('200312', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200401 VALUES LESS THAN(TO_DATE('200401', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200402 VALUES LESS THAN(TO_DATE('200402', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200403 VALUES LESS THAN(TO_DATE('200403', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200404 VALUES LESS THAN(TO_DATE('200404', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200405 VALUES LESS THAN(TO_DATE('200405', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200406 VALUES LESS THAN(TO_DATE('200406', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200407 VALUES LESS THAN(TO_DATE('200407', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200408 VALUES LESS THAN(TO_DATE('200408', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200409 VALUES LESS THAN(TO_DATE('200409', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200410 VALUES LESS THAN(TO_DATE('200410', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200411 VALUES LESS THAN(TO_DATE('200411', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200412 VALUES LESS THAN(TO_DATE('200412', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200501 VALUES LESS THAN(TO_DATE('200501', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200502 VALUES LESS THAN(TO_DATE('200502', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200503 VALUES LESS THAN(TO_DATE('200503', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200504 VALUES LESS THAN(TO_DATE('200504', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200505 VALUES LESS THAN(TO_DATE('200505', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200506 VALUES LESS THAN(TO_DATE('200506', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200507 VALUES LESS THAN(TO_DATE('200507', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200508 VALUES LESS THAN(TO_DATE('200508', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200509 VALUES LESS THAN(TO_DATE('200509', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200510 VALUES LESS THAN(TO_DATE('200510', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200511 VALUES LESS THAN(TO_DATE('200511', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200512 VALUES LESS THAN(TO_DATE('200512', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200601 VALUES LESS THAN(TO_DATE('200601', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200602 VALUES LESS THAN(TO_DATE('200602', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200603 VALUES LESS THAN(TO_DATE('200603', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200604 VALUES LESS THAN(TO_DATE('200604', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200605 VALUES LESS THAN(TO_DATE('200605', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200606 VALUES LESS THAN(TO_DATE('200606', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200607 VALUES LESS THAN(TO_DATE('200607', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200608 VALUES LESS THAN(TO_DATE('200608', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200609 VALUES LESS THAN(TO_DATE('200609', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200610 VALUES LESS THAN(TO_DATE('200610', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200611 VALUES LESS THAN(TO_DATE('200611', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200612 VALUES LESS THAN(TO_DATE('200612', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200701 VALUES LESS THAN(TO_DATE('200701', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200702 VALUES LESS THAN(TO_DATE('200702', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200703 VALUES LESS THAN(TO_DATE('200703', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200704 VALUES LESS THAN(TO_DATE('200704', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200705 VALUES LESS THAN(TO_DATE('200705', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200706 VALUES LESS THAN(TO_DATE('200706', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200707 VALUES LESS THAN(TO_DATE('200707', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200708 VALUES LESS THAN(TO_DATE('200708', 'YYYYMM')) SUBPARTITIONS 100,
PARTITION P200709 VALUES LESS THAN(TO_DATE('200709', 'YYYYMM')) SUBPARTITIONS 100,
-- 9400에서 10,000개 파티션에 근접해서 더 늘어나는 구간이라 MAXVALUE 처리함
PARTITION P5      VALUES LESS THAN(MAXVALUE)                    SUBPARTITIONS 100
);

 

② 샘플 데이터 넣기
INSERT INTO APPS.PARTITION_TEST_TAB
SELECT ADD_MONTHS(TO_DATE('200001', 'YYYYMM'), 
                  DECODE(MOD(LEVEL, 10000), 
                         0, 
                         TRUNC(LEVEL / 10000), 
                         TRUNC(LEVEL / 10000) + 1) - 1) MON_P1,
       DECODE(MOD(LEVEL, 100), 
              0, 
              TRUNC(LEVEL / 100), 
              TRUNC(LEVEL / 100) + 1) * 100 GRP_P2,
       LEVEL CNT_N1
FROM   DUAL
CONNECT BY LEVEL <= 1000000
;

COMMIT;

 

③ 통계정보
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('APPS',
                                'PARTITION_TEST_TAB',
                                CASCADE => TRUE);
END;
/

PARTITION_TEST_TAB
------------------
Rows=998,668                            Blocks=74,646
Empty Blocks=0                          Avg Space=0
Chain Count=0                           Avg Row Length=16
Avg Space Freelist Blocks=0             Freelist Blocks=0
Sample Size=56,777                      Last Analyze=2008/08/24
Partitioned=YES                        

  Column Name                      Nullable Column Type     Distinct    Buckets
  -------------------------------- -------- ------------- ---------- ----------
  MON_P1                                    DATE                 101          1
  GRP_P2                                    NUMBER             9,994          1
  CNT_N1                                    NUMBER           998,668          1

  INDEX
  -----------------------------------------------------------------------------


1. Full Table Scan
1) 파티션 키로 Full Table Scan

 

① 일반 테이블
SELECT *
FROM   NORMAL_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
AND    GRP_P2 = :B2 -- 841000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch       11    0.080        0.087          0       3064          0        100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total       13    0.080        0.088          0       3064          0        100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
    100   TABLE ACCESS FULL NORMAL_TEST_TAB (cr=3064 pr=0 pw=0 time=70247 us)

 

② 파티션 테이블
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
AND    GRP_P2 = :B2 -- 841000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch       11    0.000        0.001          0         25          0        100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total       13    0.000        0.001          0         25          0        100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
    100   PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=25 pr=0 pw=0 time=120 us)
    100    PARTITION HASH SINGLE PARTITION: KEY KEY (cr=25 pr=0 pw=0 time=96 us)
    100     TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: KEY KEY (cr=25 pr=0 pw=0 time=80 us)

 


2) 파티션 키가 아닌 것으로 Full Table Scan

 

① 일반 테이블
SELECT *
FROM   NORMAL_TEST_TAB
WHERE  CNT_N1 = :B1 -- 900000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch        2    0.400        0.412          0       3055          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.400        0.412          0       3055          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   TABLE ACCESS FULL NORMAL_TEST_TAB (cr=3055 pr=0 pw=0 time=371933 us)

 

② 파티션 테이블
-- 2개 파티션 키 모두 없이 
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  CNT_N1 = :B1 -- 900000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch        2    0.940        0.936          0      97104          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.940        0.937          0      97104          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   PARTITION RANGE ALL PARTITION: 1 94 (cr=97104 pr=0 pw=0 time=873415 us)
      1    PARTITION HASH ALL PARTITION: 1 100 (cr=97104 pr=0 pw=0 time=933492 us)
      1     TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: 1 9400 (cr=97104 pr=0 pw=0 time=924367 us)

 

-- 1개 파티션 키 선두(1블럭당 5개 로우 액세스 - 그나마 효율)
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch     1001    0.000        0.046          0       1948          0      10000
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total     1003    0.000        0.046          0       1948          0      10000

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
  10000   PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=1948 pr=0 pw=0 time=40165 us)
  10000    PARTITION HASH ALL PARTITION: 1 100 (cr=1948 pr=0 pw=0 time=40148 us)
  10000     TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION: KEY KEY (cr=1948 pr=0 pw=0 time=3704 us)

 

-- 1개 파티션 키 후발(100블럭당 8개 로우 액세스 - 비효율적)
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  GRP_P2 = :B2 -- 841000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch       11    0.010        0.013          0       1240          0        100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total       13    0.010        0.013          0       1240          0        100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
    100   PARTITION RANGE ALL PARTITION: 1 94 (cr=1240 pr=0 pw=0 time=10802 us)
    100    PARTITION HASH SINGLE PARTITION: KEY KEY (cr=1240 pr=0 pw=0 time=12343 us)
    100     TABLE ACCESS FULL PARTITION_TEST_TAB PARTITION:   (cr=1240 pr=0 pw=0 time=11913 us)

 

-- 파티션 키에서 선두 없이 후발만 들어오게 되면 비효율적

2. Index Ragne Scan
1) 인덱스 생성

 

① 일반 테이블
CREATE INDEX APPS.NORMAL_TEST_TAB_N1 on APPS.NORMAL_TEST_TAB (MON_P1)         
    TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;
CREATE INDEX APPS.NORMAL_TEST_TAB_N2 on APPS.NORMAL_TEST_TAB (MON_P1, GRP_P2) 
    TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;
CREATE INDEX APPS.NORMAL_TEST_TAB_N3 on APPS.NORMAL_TEST_TAB (CNT_N1)         
    TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;                                      

ALTER INDEX APPS.NORMAL_TEST_TAB_N1 NOPARALLEL;
ALTER INDEX APPS.NORMAL_TEST_TAB_N2 NOPARALLEL;
ALTER INDEX APPS.NORMAL_TEST_TAB_N3 NOPARALLEL;

 

② 파티션 테이블
-- Local Prefixed Index
CREATE INDEX APPS.PARTITION_TEST_TAB_N1 on APPS.PARTITION_TEST_TAB (MON_P1)         
    TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6 LOCAL;
CREATE INDEX APPS.PARTITION_TEST_TAB_N2 on APPS.PARTITION_TEST_TAB (MON_P1, GRP_P2) 
    TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6 LOCAL;

-- Global Prefixed Index
CREATE INDEX APPS.PARTITION_TEST_TAB_N3 on APPS.PARTITION_TEST_TAB (CNT_N1)         
    GLOBAL PARTITION BY RANGE(CNT_N1) (PARTITION P1  VALUES LESS THAN (100000),
                                       PARTITION P2  VALUES LESS THAN (200000),
                                       PARTITION P3  VALUES LESS THAN (300000),
                                       PARTITION P4  VALUES LESS THAN (400000),
                                       PARTITION P5  VALUES LESS THAN (500000),
                                       PARTITION P6  VALUES LESS THAN (600000),
                                       PARTITION P7  VALUES LESS THAN (700000),
                                       PARTITION P8  VALUES LESS THAN (800000),
                                       PARTITION P9  VALUES LESS THAN (900000),
                                       PARTITION P10 VALUES LESS THAN (1000000),
                                       PARTITION P11 VALUES LESS THAN (MAXVALUE))   
        TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6;

ALTER INDEX APPS.PARTITION_TEST_TAB_N1 NOPARALLEL;
ALTER INDEX APPS.PARTITION_TEST_TAB_N2 NOPARALLEL;
ALTER INDEX APPS.PARTITION_TEST_TAB_N3 NOPARALLEL;


3) 통계정보

 

① 일반 테이블
NORMAL_TEST_TAB
---------------
Rows=997,141                            Blocks=3,032
Empty Blocks=0                          Avg Space=0
Chain Count=0                           Avg Row Length=16
Avg Space Freelist Blocks=0             Freelist Blocks=0
Sample Size=54,167                      Last Analyze=2008/08/24
Partitioned=NO                         

  Column Name                      Nullable Column Type     Distinct    Buckets
  -------------------------------- -------- ------------- ---------- ----------
  MON_P1                                    DATE                 101          1
  GRP_P2                                    NUMBER             9,999          1
  CNT_N1                                    NUMBER           997,141          1

  INDEX
  -----------------------------------------------------------------------------
  NORMAL_TEST_TAB_N1 : MON_P1
      Type=NORMAL, Uniq=No, Distinct=100, Rows=1,000,000, Last Analyze=2008/08/24
  NORMAL_TEST_TAB_N2 : MON_P1 + GRP_P2
      Type=NORMAL, Uniq=No, Distinct=10,000, Rows=1,000,000, Last Analyze=2008/08/24
  NORMAL_TEST_TAB_N3 : CNT_N1
      Type=NORMAL, Uniq=No, Distinct=1,000,000, Rows=1,000,000, Last Analyze=2008/08/24

 

② 파티션 테이블
PARTITION_TEST_TAB
------------------
Rows=998,668                            Blocks=74,646
Empty Blocks=0                          Avg Space=0
Chain Count=0                           Avg Row Length=16
Avg Space Freelist Blocks=0             Freelist Blocks=0
Sample Size=56,777                      Last Analyze=2008/08/24
Partitioned=YES                        

  Column Name                      Nullable Column Type     Distinct    Buckets
  -------------------------------- -------- ------------- ---------- ----------
  MON_P1                                    DATE                 101          1
  GRP_P2                                    NUMBER             9,994          1
  CNT_N1                                    NUMBER           998,668          1

  INDEX
  -----------------------------------------------------------------------------
  PARTITION_TEST_TAB_N1 : MON_P1
      Partition=LOCAL NON_PREFIXED
      Type=NORMAL, Uniq=No, Distinct=8, Rows=1,000,000, Last Analyze=2008/08/24
  PARTITION_TEST_TAB_N2 : MON_P1 + GRP_P2
      Partition=LOCAL PREFIXED
      Type=NORMAL, Uniq=No, Distinct=10,000, Rows=1,000,000, Last Analyze=2008/08/24
  PARTITION_TEST_TAB_N3 : CNT_N1
      Partition=GLOBAL PREFIXED
      Type=NORMAL, Uniq=No, Distinct=1,000,000, Rows=1,000,000, Last Analyze=2008/08/24


4) 테스트

 

① 일반 테이블
SELECT *
FROM   NORMAL_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
AND    GRP_P2 = :B2 -- 841000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch       11    0.000        0.000          0         24          0        100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total       13    0.000        0.001          0         24          0        100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
    100   TABLE ACCESS BY INDEX ROWID NORMAL_TEST_TAB (cr=24 pr=0 pw=0 time=36 us)
    100    INDEX RANGE SCAN NORMAL_TEST_TAB_N2 (cr=13 pr=0 pw=0 time=621 us)(Object ID 2885525)

SELECT *
FROM   NORMAL_TEST_TAB
WHERE  CNT_N1 = :B1 -- 900000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch        2    0.000        0.000          0          5          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.000        0.000          0          5          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   TABLE ACCESS BY INDEX ROWID NORMAL_TEST_TAB (cr=5 pr=0 pw=0 time=40 us)
      1    INDEX RANGE SCAN NORMAL_TEST_TAB_N3 (cr=4 pr=0 pw=0 time=36 us)(Object ID 2885526)

 

② 파티션 테이블
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
AND    GRP_P2 = :B2 -- 841000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch       11    0.000        0.001          0         23          0        100
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total       13    0.000        0.001          0         23          0        100

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
    100   PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=23 pr=0 pw=0 time=71 us)
    100    PARTITION HASH SINGLE PARTITION: KEY KEY (cr=23 pr=0 pw=0 time=55 us)
    100     TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: KEY KEY (cr=23 pr=0 pw=0 time=46 us)
    100      INDEX RANGE SCAN PARTITION_TEST_TAB_N2 PARTITION: KEY KEY (cr=12 pr=0 pw=0 time=826 us)(Object ID 2895022)

-- Global Prefixed Index
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  CNT_N1 = :B1 -- 900000
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch        2    0.000        0.000          0          4          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.000        0.000          0          4          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=49 us)
      1    TABLE ACCESS BY GLOBAL INDEX ROWID PARTITION_TEST_TAB PARTITION: ROW LOCATION ROW LOCATION (cr=4 pr=0 pw=0 time=35 us)
      1     INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: KEY KEY (cr=3 pr=0 pw=0 time=30 us)(Object ID 2904517)
;

-- Local Non-Prefixed Index
DROP INDEX APPS.PARTITION_TEST_TAB_N3;

CREATE INDEX APPS.PARTITION_TEST_TAB_N3 on APPS.PARTITION_TEST_TAB (CNT_N1) TABLESPACE APPS_TS_TX_IDX COMPUTE STATISTICS PARALLEL 6 LOCAL;

-- FULL COLUMN
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
AND    GRP_P2 = :B2 -- 841000
AND    CNT_N1 = :B3 -- 840936
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.000          0          0          0          0
Fetch        2    0.000        0.000          0          4          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.000        0.000          0          4          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=99 us)
      1    PARTITION HASH SINGLE PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=73 us)
      1     TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: KEY KEY (cr=4 pr=0 pw=0 time=55 us)
      1      INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: KEY KEY (cr=3 pr=0 pw=0 time=41 us)(Object ID 2904529)

 

-- 후발 없이(선두키가 없으면 PARALLEL 처리할 떄 보이는 실행계획 나옴)
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  MON_P1 = :B1 -- 2007/01/01
AND    CNT_N1 = :B3 -- 840936
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.018          0        200          0          0
Fetch        2    0.010        0.117          0          0          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.010        0.135          0        200          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   PX COORDINATOR  (cr=200 pr=0 pw=0 time=37561 us)
      0    PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us)
      0     PX PARTITION HASH ALL PARTITION: 1 100 (cr=0 pr=0 pw=0 time=0 us)
      0      TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION: KEY KEY (cr=0 pr=0 pw=0 time=0 us)
      0       INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION: KEY KEY (cr=0 pr=0 pw=0 time=0 us)(Object ID 2904529)

 

-- 선두 없이(선두키가 없으면 PARALLEL 처리할 떄 보이는 실행계획 나옴)
SELECT *
FROM   PARTITION_TEST_TAB
WHERE  GRP_P2 = :B2 -- 841000
AND    CNT_N1 = :B3 -- 840936
;

Call     Count CPU Time Elapsed Time       Disk      Query    Current       Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse        1    0.000        0.000          0          0          0          0
Execute      1    0.000        0.009          0        188          0          0
Fetch        2    0.010        0.135          0          0          0          1
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total        4    0.010        0.144          0        188          0          1

Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: APPS (ID=44)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  STATEMENT
      1   PX COORDINATOR  (cr=188 pr=0 pw=0 time=46595 us)
      0    PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us)
      0     PX PARTITION HASH SINGLE PARTITION: KEY KEY (cr=0 pr=0 pw=0 time=0 us)
      0      TABLE ACCESS BY LOCAL INDEX ROWID PARTITION_TEST_TAB PARTITION:   (cr=0 pr=0 pw=0 time=0 us)
      0       INDEX RANGE SCAN PARTITION_TEST_TAB_N3 PARTITION:   (cr=0 pr=0 pw=0 time=0 us)(Object ID 2904529)


출처 : http://blog.daum.net/warmfeel/82


Posted by 아로나
Database/Oracle2014. 5. 19. 14:16
/*
    # CLOB 형 데이타 SELECT
      
    DBMS_LOB.SUBSTR(
     CLOB 타입 컬럼 명
    , 추출할 문자열 길이(숫자) OR 전체 문자길이( DBMS_LOB.GETLENGTH(CONTENTS) )
    , 전체 값 출력 : 1
    )
      
    전체 문자길이( DBMS_LOB.GETLENGTH(CONTENTS) ) 사용시 아래와 같은 메세지 발생할 수 있음. 
    -- ORA-06502: PL/SQL: 수치 또는 값 오류: 문자열 버퍼가 너무 작습니다   

   ==>  DBMS_LOB.GETLENGTH(CONTENTS)의 길이가 4000이상인 경우 발생하는 듯함. 원인은 아래 내용 참조

*/
 
SELECT  DBMS_LOB.SUBSTR(CONTENTS, 1000, 1) AS CONT_SUB   -- 1000 개까지 출력(문자열)
        , DBMS_LOB.INSTR(CONTENTS, 'TEST', 1, 1) AS CONT_INS   -- 검색 문구의 위치 출력(숫자)
  FROM CLOB_TABLE
  WHERE DBMS_LOB.INSTR(CONTENTS, 'TEST', 1, 1) > 0             -- 검색 문구가 존재할때
;

* ORA-06502: PL/SQL: 수치 또는 값 오류: 문자열 버퍼가 너무 작습니다 의 원인

DBMS_LOB.SUBSTR (
   lob_loc     IN    BLOB,
   amount      IN    INTEGER := 32767,
   offset      IN    INTEGER := 1)
  RETURN RAW;

DBMS_LOB.SUBSTR (
   lob_loc     IN    CLOB   CHARACTER SET ANY_CS,
   amount      IN    INTEGER := 32767,
   offset      IN    INTEGER := 1)
  RETURN VARCHAR2 CHARACTER SET lob_loc%CHARSET;

DBMS_LOB.SUBSTR (
   file_loc     IN    BFILE,
   amount      IN    INTEGER := 32767,
   offset      IN    INTEGER := 1)
  RETURN RAW;

 

Parameters

Table 52-52 SUBSTR Function Parameters

Parameter

Description

lob_loc

Locator for the LOB to be read. For more information, see Operational Notes.

file_loc

The file locator for the LOB to be examined.

amount

Number of bytes (for BLOBs) or characters (for CLOBs) to be read.

offset

Offset in bytes (for BLOBs) or characters (for CLOBs) from the start of the LOB (origin: 1).

 

(출처: http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lob.htm#i999349)

 

CLOB일 경우, Byte가 아니라 문자 갯수가 4000자로 잘려진다고 합니다.

 

즉, 문자셋이 한글이나 UTF-8 등으로 되어 있을 경우, 4000자를 가져오면 4000 Byte를 넘기 때문에,

VARCHAR2 에 저장할 수 있는 한계에 걸려, 해당 오류가 발생합니다.


또한, DBMS_LOB.SUBSTR(...) 함수의 리턴 값이 VARCHAR2로 지정되어 있어서,

이 함수를 SQL 문장에서 직접 사용할 경우, 함수가 리턴될 때 바로 4000Byte 제한이 걸리게 됩니다.

때문에, 위에서도 INSERT가 아닌 DBMS_LOB.SUBSTR(...) 함수가 수행된 바로 직후에 에러가 발생할 것입니다.

 

질문하신 내용도, 2000 Byte 까지만 저장된다는 걸로 보아, 같은 상황인 것 같습니다.

 

해결 방법은, 여러 가지가 있을 것 같은데요,


1. 1000 또는 2000 Byte씩 나누어 받은 합치는 방법
   - 번거롭지만, 어쩔 수 없는 경우엔 쓸 만합니다.
   TO_CLOB(DBMS_LOB.substr(...)) || 
TO_CLOB(DBMS_LOB.substr(...)) 이런 식으로 사용하면 됩니다.


2. 글자수가 아닌 Byte 잘라오는 방법을 쓸 수도 있습니다

  - CLOB는 기본적으로 Byte로 자르는 방법을 지원하지 않는 것 같습니다.

  - LOB등의 다른 형식으로 변환한 후 DBMS_LOB.substr(...)   를 사용하면 byte로 잘라집니다.


3.  SUBSTR(...)로도 CLOB를 처리할 수 있습니다.

  즉, DBMS_LOB.SUBSTR(..4000, 1) 대신 SUBSTR(..,1,4000) 을 사용하는 식입니다.


4. PL/SQL의 VARCHAR2 크기는 4000 Byte가 아닌, 32767 Byte 까지 확장됩니다.

    PL/SQL로 프로시저 내부에서 DBMS_LOB.SUBSTR(..,4000,.)를 이용해 결과를 얻어오는 것도 방법이 될 수 있습니다.


저는 1,2,3 번으로 해보았는데요,

2번은 문자가 깨질 가능성이 있고, 1,3번은 시스템 환경에 따라 안먹히는 경우가 있습니다.

현재로선 번거롭더라도 PL/SQL을 직접 작성하는 것이 제일 안전해 보입니다.


혹시, 더 좋은 방법이 있다면 공유 부탁드려요,

저도, 나중에라도 좋은 방법을 찾으면 업데이트 하겠습니다.

 출처 : http://develop.sunshiny.co.kr/841

http://www.dator.co.kr/256804

Posted by 아로나
Database/Oracle2013. 9. 27. 09:12

connection, statement, resultset중 어느거라도 close() 한후에 resultset으로부터 값을 얻을려고 하거나
resultset의 범위를 넘어선 상태에서 값을 얻을려고 하면

"결과 집합을 모두 소모했음"

connection, statement, resultset중 어느거라도 close() 한후에 resultset의 next()를 호출하면

"xxx[을] 종료[했음]"

 

==> 즉, rs.next() 로 데이터를 불러 오는 상황 이전에, 커넥션이 특정 상황으로 인해 close되어 있어서 발생하는

오류에 해당.

Posted by 아로나
Database/Oracle2013. 9. 27. 09:05

 

JDBC의 ResultSet 에서 rs.next() 를 돌려서 결과를 뿌려줄 때 rs.next() 의 값이 더 이상 존재하지 않을 때 이런 에러가 발생함.

보통 while(rs.next()){              } 와 같은 형식으로 사용하면 이럴 일이 없는데, 다른 방법으로 루프를 돌리며 ResultSet을 가져오려 할 때 발생하는 듯 함.

 

출처 : http://happybruce.tistory.com/entry/SQLException-%EA%B2%B0%EA%B3%BC%EC%A7%91%ED%95%A9%EC%9D%84-%EB%AA%A8%EB%91%90-%EC%86%8C%EB%AA%A8%ED%96%88%EC%9D%8C

Posted by 아로나
Database/Oracle2013. 9. 27. 09:03

도움 되는 유용 사이트
http://blog.naver.com/blubeard/80058348146

 java.sql.SQLException: ORA-01000: 최대 열기 커서 수를 초과했습니다
가 나는 원인은

// 포문을 돌면서..
for(){
   // 너무 많은 psmt 와 rs를 쓰기만 하고 닫아주지 않아서 남.
   kwan_pstmt = kwan_conn.prepareStatement("SELECT ....문 들어감.");
   kwan_rs = kwan_pstmt.executeQuery();
}


* 해결책

 

try{
   내용..
} catch(SQLException e) {
      System.out.println("getHistoryResultList: " + e.toString());
} finally{
     if(kwan_pstmt != null) try{kwan_pstmt.close();}catch(SQLException ex){}
     if(kwan_rs != null) try{kwan_rs.close();}catch(SQLException ex){}
}


으로 rs와 pstmt 를 닫아 주었다.
conn은 나중에 전체적으로 닫아주면 된다. 다 사용한 뒤에 ^^..

- 끝 -

Posted by 아로나
Database/Oracle2013. 9. 3. 10:28

Import 툴(imp, impdp)에 의한 논리적 복구


논리적 복구인 임포트(import)는 논리적 백업인 익스포트된 덤프 파일로부터 객체 정의와 테이블 데이터를 읽어서 데이터 객체를 오라클 데이터베이스에 삽입한다.
익스포트 덤프파일은 오라클 임포트에 의해서만 읽을 수 있고, 임포트 유틸리티의 버전이 덤프 파일을 생성하기 위해 사용된 익스포트 유틸리티 버전보다 낮은 경우에는 읽어 올 수 없다.


테이블 객체 임포트하기

테이블 객체를 익스포트 유틸리티를 사용하여 익스포트하여 생성된 익스포트 파일은 다음과 같은 순서로 객체를 포함한다.

	1) 타입정의
	2) 테이블 정의
	3) 테이블 데이터
	4) 테이블 인덱스
	5) 무결성 제약조건, 뷰, 프로시져와 트리거
	6) 비트맵 인덱스, 함수기반 인덱스와 도메인 인덱스

따라서 먼저 새로운 테이블이 생성되고, 데이터가 임포트 된 다음 인덱스가 생성된다. 그 다음에 트리거가 임포트되고, 무결성 제약조건이 생성된 테이블에 활성화된다. 그런 다음 비트맵 인덱스, 함수기반 인덱스와 도메인 인덱스가 생성된다. 이러한 순서는 테이블이 임포트되는 순서에 의해 에러가 발생하지 않도록 하기 위해서이다.

익스포트와 마찬가지로 임포트 유틸리티를 사용하기 전에 catexp.sql이나 catalog.sql 스크립트를 실행하고, 임포트할 권한을 가져야 한다.

임포트하려면 CREATE SESSION 권한을 가져야 하는데, 이 권한은 CONNECT 롤에 포함되어 있고, 자신의 스키마에 객체를 임포트하기 위해서 필요한 권한은 RESOURCE 롤에 포함되어 있다. 사용자가 익스포트한 파일이 아니고 다른 사용자가 익스포트한 파일을 임포트하려면 IMP_FULL_DATBASE 롤을 가지고 있어야 한다.


임포트 실행하기

임포트를 실행하는 방법은 다음과 같은 세가지 방법이 가능하다.
1) 명령행에서 실행하기
명령어 행에서 임포트를 실행하기 위한 명령문은 다음 두가지 모두 가능하다.

IMP username/password PARAMETER=값

IMP username/password PARAMETER=(값1,값2,...)

2) 인터렉티브 모드에서 실행하기
임포트를 실행하기 위한 매개변수를 직접 입력하여 실행하는 방법으로 다음과 같은 방법이 사용 가능하다.

입력 동작
imp username/password@instance as sysdba 임포트 세션 실행
imp username/password@instance 임포트 세션 실행
imp username/password as sysdba 임포트 세션 실행
imp username/password 임포트 세션 실행
imp username@instance as sysdba password입력을 위한 프롬프트
imp username@instance password입력을 위한 프롬프트
imp username password입력을 위한 프롬프트
imp username as sysdba password 입력을 위한 프롬프트
imp / as sysdba password 확인없이 실행
imp / password 확인없이 실행
imp /@instance as sysdba password 확인없이 실행
imp /@instance password 확인없이 실행

3) 매개변수 파일을 사용하여 실행하기
매개변수 파일에 매개변수의 값을 저장하고 명령어 행에 PARFILE 옵션을 사용하여 명시하는 방법으로 다음과 같이 사용한다.

        imp PARFILE=파일이름
        imp username/password PARFILE=파일이름
매개변수 파일은 다음 형식중의 하나처럼 작성할 수 있다.
        PARAMETER=value
        PARAMETER=(value)
        PARAMETER=(value1,value2,...)

• 다음은 Import 유틸리티에서 사용할 수 있는 키워드이다.

키워드 의미
USERID/PASSWORD 복구할 사용자 id와 암호를 입력
BUFFER 데이터를 읽어올 버퍼의 크기, 0이면 한번에 1행씩 읽음
FILE 운영체제상에 저장된 백업 파일명, 디폴트=expdat.dmp
SHOW 실제 복구작업은 하지 않고 백업파일의 내용만 보여줌
TABLES import될 table의 이름
INDEXS index가 포함하여 import함(디폴트=Y)
ROWS Y이면 데이터베이스 객체 내의 모든 행을 import함,
N이면 임의의 데이터베이스 객에 대한 DDL 정보만 import함(디폴트=Y)
FROMUSER import되는 object의 소유자 list
TOUSER FROMUSER에 대한 다른 사용자 ID를 정의
FULL Y값은 전체 DB의 import를 설정,
사용을 위해서는 exp_full_database의 role이 있어야 함(디폴트=N)
COMMIT • commit의 단위를 결정함
• Y로 설정하면 각 배열이 삽입된 후 commit되도록 지정
• N은 명시적 commit이 아니라 다음 transaction을 create하면 auto-commit되도록 지정
• Y로 설정하면 rollback segment가 과도하게 많아지는 것을 방지함
• 디폴트=N
GRANTS import될 때 모든 object에 부여된 role까지도 포함하여 import함
PARFILE 자주 사용하는 import 옵션을 모아서 실행할 때 사용
LOG import 작업시 모든 로그 내용을 지정한 파일에 저장
DESTROY 이미 존재하는 객체를 복구할 때 삭제 후 복구
TRANSPORT_TABLESPACE=Y 데이터베이스 간에 tablespace를 이동시킬 때 사용
INDEXFILE 복구시 사용한 index 관련 문법을 지정한 파일에 저장
IGNORE • Y이면, object 생성에 중복등이 있어 object가 생성되지 않는 error가 발생시 아무런message없이 기존 table로 import함
• N이면, error가 출력되며 이미 존재하는 TABLE은 건너 뜀
• 단, 이 parameter는 object 생성 error만 무시할 수 있고, 다른 여러 error에는 영향을 끼치지 않음(디폴트=N)
FEEDBACK 아무런 표현이 없을 시 import 실행 과정이 ....처럼 행의 개수만큼 점으로 표시됨
RECORDLENGTH 입력 record의 크기를 지정해 줌, data가 다른 record 크기를 가진 운영체제로 export된 경우에만 사용함
PARLOG import parameter의 list를 가지고 있는 LOG이름을 지정
SHOW • Y이면, import할 내용의 SQL문이 출력되고 import는 수행되지 않음
• import가 실행할 순서대로 SQL문이 출력됨
• SHOW=Y이면 FROMUSER, TOUSER, FULL, TABLES PARAMETER만 설정될 수 있음
HELP • parameter의 의미를 출력함
• Y로 설정하면 import는 실행되지 않고 도움말이 출력됨


parameter 사용시 주의할 사항

-- FULL=Y, OWNER=user, TABLE=schema.TABLE 파라미터는 IMPORT MODE를 지정하는 파라미터이기 때문에 함께 사용될 수 없다.
-- 같은 파라미터 값으로 여러 번 IMPORT를 수행하는 경우 PARAMETER LOG를 만들어서 PARLOG로 명시하여 사용하는 것이 좋다.


import는 다음과 같은 4 가지 모드로 복구 할 수 있다. 물론 데이텁제이스 모드나 테이블스페이스 모드를 사용하려거나 다른 사용자의 테이블이을 사용하려면 당연히 imp_full_database롤이 있어야 한다.

    데이터베이스 전체모드
    tablespace mode
    사용자 모드
    테이블 모드
오라클 10g 버전부터는 impdp 유틸리티를 사용하여 서버에 data pump import할 수 있도록 하였다.

【예제】 $ imp help=Y

Import: Release 11.1.0.6.0 - Production on Wed Jun 10 12:50:24 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.



You can let Import prompt you for parameters by entering the IMP
command followed by your username/password:

     Example: IMP SCOTT/TIGER

Or, you can control how Import runs by entering the IMP command followed
by various arguments. To specify parameters, you use keywords:

     Format:  IMP KEYWORD=value or KEYWORD=(value1,value2,...,valueN)
     Example: IMP SCOTT/TIGER IGNORE=Y TABLES=(EMP,DEPT) FULL=N
               or TABLES=(T1:P1,T1:P2), if T1 is partitioned table

USERID must be the first parameter on the command line.

Keyword  Description (Default)       Keyword      Description (Default)
--------------------------------------------------------------------------
USERID   username/password           FULL         import entire file (N)
BUFFER   size of data buffer         FROMUSER     list of owner usernames
FILE     input files (EXPDAT.DMP)    TOUSER       list of usernames
SHOW     just list file contents (N) TABLES       list of table names
IGNORE   ignore create errors (N)    RECORDLENGTH length of IO record
GRANTS   import grants (Y)           INCTYPE      incremental import type
INDEXES  import indexes (Y)          COMMIT       commit array insert (N)
ROWS     import data rows (Y)        PARFILE      parameter filename
LOG      log file of screen output   CONSTRAINTS  import constraints (Y)
DESTROY                overwrite tablespace data file (N)
INDEXFILE              write table/index info to specified file
SKIP_UNUSABLE_INDEXES  skip maintenance of unusable indexes (N)
FEEDBACK               display progress every x rows(0)
TOID_NOVALIDATE        skip validation of specified type ids 
FILESIZE               maximum size of each dump file
STATISTICS             import precomputed statistics (always)
RESUMABLE              suspend when a space related error is encountered(N)
RESUMABLE_NAME         text string used to identify resumable statement
RESUMABLE_TIMEOUT      wait time for RESUMABLE 
COMPILE                compile procedures, packages, and functions (Y)
STREAMS_CONFIGURATION  import streams general metadata (Y)
STREAMS_INSTANTIATION  import streams instantiation metadata (N)
VOLSIZE                number of bytes in file on each volume of a file on tape

The following keywords only apply to transportable tablespaces
TRANSPORT_TABLESPACE import transportable tablespace metadata (N)
TABLESPACES tablespaces to be transported into database
DATAFILES datafiles to be transported into database
TTS_OWNERS users that own data in the transportable tablespace set

Import terminated successfully without warnings.
$

EXPORT/IMPORT할 때 CHARACTER SET
1) EXPORT
• CONVENTIONAL PATH인 경우에는 USER SESSION에 지정된 CHARACTER SET을 따른다.
• DIRECT PATH인 경우에는 DATABASE CHARACTER SET을 따른다. 만약, USER SESSION과 DATABASE CHARACTER SET이 다른 경우에는 DIRECT PATH로 사용하면 EXPORT작업은 경고 message와 함께 중지된다.

2) IMPORT
• IMPORT되는 SESSION과 DATABASE의 CHARACTER SET이 다르면 먼저 USER SESSION의 CHARACTER SET으로 변경 시키고 다시 DATABASE CHARACTER SET으로 변경한다.
이는 변경하는데 많은 시간이 걸리며, 또한 일치하는 문자가 없을 경우에는 DATA의 누락이 있을 수 있다.


【예제】☜
exp 과정

$ exp userid=scott/tiger tables=(scott.emp)

Export: Release 11.1.0.6.0 - Production on Thu Jun 4 12:51:01 2009

Copyright (c) 1982, 2007, Oracle.  All rights reserved.


Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - 64bit
Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Export done in KO16KSC5601 character set and AL16UTF16 NCHAR character set
server uses KO16MSWIN949 character set (possible charset conversion)

About to export specified tables via Conventional Path ...
. . exporting table                            EMP         14 rows exported
EXP-00091: Exporting questionable statistics.
"exp_tables.html" 34 행, 1077 문자
Export terminated successfully with warnings.
$
파일확인

$ ls -l expdat.dmp
-rw-r--r--   1 jijoe    junik       7168  6월  4일  12:51 expdat.dmp
$ file expdat.dmp
expdat.dmp:     데이터
$
imp 과정

먼저 해당 테이블을 drop한 다음에 
$ imp userid=scott/tiger file=expdat.dmp tables=emp Import: Release 11.1.0.6.0 - Production on Sun Jun 7 12:18:59 2009 Copyright (c) 1982, 2007, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options Export file created by EXPORT:V11.01.00 via conventional path import done in KO16KSC5601 character set and AL16UTF16 NCHAR character set import server uses KO16MSWIN949 character set (possible charset conversion) . importing SCOTT's objects into SCOTT . importing SCOTT's objects into SCOTT . . importing table "EMP" 14 rows imported Import terminated successfully without warnings. $

【예제】☜ $ imp userid=scott/tiger full=y

Import: Release 10.2.0.2.0 - Production on Sun Jun 7 10:32:27 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production
With the Partitioning, OLAP and Data Mining options

Export file created by EXPORT:V10.02.01 via conventional path
import done in KO16KSC5601 character set and AL16UTF16 NCHAR character set
. importing SCOTT's objects into SCOTT
IMP-00015: following statement failed because the object already exists:
 "CREATE TABLE "BONUS" ("ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "SAL" NUMBER"
 ", "COMM" NUMBER)  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INI"
 "TIAL 65536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)              "
 "      LOGGING NOCOMPRESS"
IMP-00015: following statement failed because the object already exists:
 "CREATE TABLE "DEPT" ("DEPTNO" NUMBER(2, 0), "DNAME" VARCHAR2(14), "LOC" VAR"
 "CHAR2(13))  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 6"
 "5536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)                    "
 "LOGGING NOCOMPRESS"
IMP-00015: following statement failed because the object already exists:
 "CREATE TABLE "EMP" ("EMPNO" NUMBER(4, 0), "ENAME" VARCHAR2(10), "JOB" VARCH"
 "AR2(9), "MGR" NUMBER(4, 0), "HIREDATE" DATE, "SAL" NUMBER(7, 2), "COMM" NUM"
 "BER(7, 2), "DEPTNO" NUMBER(2, 0))  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRAN"
 "S 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAU"
 "LT)                    LOGGING NOCOMPRESS"
IMP-00015: following statement failed because the object already exists:
 "CREATE TABLE "SALGRADE" ("GRADE" NUMBER, "LOSAL" NUMBER, "HISAL" NUMBER)  P"
 "CTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELIST"
 "S 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)                    LOGGING NOCOM"
 "PRESS"
Import terminated successfully with warnings.
$
자료 사전 정보 조회

v$instance현재 운용중인 데이터베이스에 설정된 제한조건에 대한 정보
v$database현재 데이터베이스의 체크포인트, 아카이브 모드 설정값
v$datafile_header데이터 파일의 위치와 이름과 헤더 확인
v$log리두 로그 파일의 시퀀스 번호와 현재 아카이브 상태 확인
v$tablespace데이터베이스 내의 테이블스페이스의 위치와 이름 확인
v$recover_file현재 데이터 파일의 온라인 여부 확인
v$backup데이터 파일의 번호, 현재상태, 시스템 체인지 번호, 데이터 파일의 상태가 변경된 시점
v$datafile_header데이터 파일의 번호, 현재상태, 생성 시점,저장될 테이블스페이스, 데이터 파일의 위치와 이름


출처 : http://radiocom.kunsan.ac.kr/lecture/oracle/backup_restore/imp.html


Posted by 아로나