- 주문 테이블에 입력하려고 백업해 둔 임시 테이블에는 2020년 1월부터 2021년 10월까지의 주문 데
이터가 입력돼 있음
- 예상치 못한 주문일시 입력되더라도 에러가 발생하지 않아야 함
- 파티션 명명 규칙은 자유롭게 지정
CREATE TABLE 주문 (
주문번호 NUMBER
, 주문일시 DATE
, 고객 ID VARCHAR2(5)
, 주문금액 NUMBER )
??
PARTITION BY RANGE (주문일시) (
PARTITION P1 VALUES LESS THAN (TO_DATE('20200701','YYYYMMDD')) ,
PARTITION P2 VALUES LESS THAN (TO_DATE('20210101','YYYYMMDD')) ,
PARTITION P3 VALUES LESS THAN (TO_DATE('20210701','YYYYMMDD')) ,
PARTITION P4 VALUES LESS THAN (TO_DATE('20220101','YYYYMMDD')) ,
PARTITION P_MAX VALUES LESS THAN (MAXVALUE)
);
✅ RANGE 파티셔닝 구문
PARTITION BY RANGE (컬럼명) ( PARTITION P1 VALUES LESS THAN (컬럼 범위1) , PARTITION P2 VALUES LESS THAN (컬럼 범위2) , PARTITION P3 VALUES LESS THAN (컬럼 범위3) , PARTITION P4 VALUES LESS THAN (컬럼 범위4) , .... PARTITION P_MAX VALUES LESS THAN (MAXVALUE) );
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일자)
SUBPARTITION BY HASH(고객ID) SUBPARTITIONS 8
(PARTITION P2020_Q1 VALUES LESS THAN("20200401")
PARTITION P2020_Q2 VALUES LESS THAN("20200701")
PARTITION P2020_Q3 VALUES LESS THAN("20201001")
PARTITION P2020_Q4 VALUES LESS THAN('20210101')
PETITION P2022_Q1 VALUES LESS THAN('20210401')
PARTITION P9999_MX VALUES LESS THAN (MAXVALUE));
SELECT * FROM 주문
WHERE 주문일자 BETWEEN '20200701' AND '20200930';
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일자)
SUBPARTITION BY HASH(고객ID) SUBPARTITIONS 8
(PARTITION P2020_Q1 VALUES LESS THAN("20200401")
PARTITION P2020_Q2 VALUES LESS THAN("20200701")
PARTITION P2020_Q3 VALUES LESS THAN("20201001")
PARTITION P2020_Q4 VALUES LESS THAN('20210101')
PETITION P2022_Q1 VALUES LESS THAN('20210401')
PARTITION P9999_MX VALUES LESS THAN (MAXVALUE));
SELECT * FROM 주문
WHERE 고객ID =:CUST_ID ;
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일자)
SUBPARTITION BY HASH(고객ID) SUBPARTITIONS 8
(PARTITION P2020_Q1 VALUES LESS THAN("20200401")
PARTITION P2020_Q2 VALUES LESS THAN("20200701")
PARTITION P2020_Q3 VALUES LESS THAN("20201001")
PARTITION P2020_Q4 VALUES LESS THAN('20210101')
PETITION P2022_Q1 VALUES LESS THAN('20210401')
PARTITION P9999_MX VALUES LESS THAN (MAXVALUE));
SELECT * FROM 주문
WHERE 고객ID =:CUST_ID
AND 주문일자 BETWEEN '20200701' AND '20201231';
✅ 파티션 Pruning
- 파티셔닝을 통해 SQL 성능을 향상해 주는 핵심 원리이다.
- 파티션 Pruning은 SQL 하드파싱이나 실행 시점에 SQL 조건절을 분석해서 읽지 않아도 되는 특이 세그먼트를 액세스 대상에서 제외하는 기능이다.
SELECT /*+ LEADING(A) USE_NL(B) */ *
FROM A, B
WHERE A.NO = B.NO;
✅ 정적(Static) 파티션 Pruning
- 파티션 키 컬럼을 상수 조건으로 조회하는 경우에 작동한다.
- 액세스할 파티션이 쿼리 최적화 시점에 미리 결정된다.
- 실행계획의 Pstart(partition start)와 Pstop(partition stop) 컬럼에는 액세스할 파티션 번호가 출력된다.
✅ 동적(Dynamic) 파티션 Pruning
- 파티션 키 컬럼을 바인드 변수로 조회하며 쿼리 최적화 시점에는 액세스할 파티션을 미리 결정할 수 없다.
- ⭐️실행 시점이 돼서야 사용자가 입력한 값에 따라 결정되며, 실행계획의 Pstart와 Pstop 컬럼에는 "KEY'라고 표시된다.⭐️
- ⭐️NL 조인할 때도 Inner 테이블이 조인 컬럼 기준으로 파티셔닝 돼 있다면 동적 Pruning이 작동한다.⭐️
CREATE TABLE 주문 (주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), … )
PARTITION BY RANGE (주문일자)
( PARTITION P01 VALUES LESS THAN('20200401')
, PARTITION P02 VALUES LESS THAN('20200701')
, PARTITION P03 VALUES LESS THAN('20201001')
, PARTITION P04 VALUES LESS THAN('20210101')
, PARTITION P05 VALUES LESS THAN('20210401')
, PARTITION PMX VALUES LESS THAN ( MAXVALUE )
);
SELECT COUNT(*) FROM 주문
WHERE 주문일자 BETWEEN '20200701' AND '20201231';
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일자)
SUBPARTITION BY HASH(고객ID) SUBPARTITIONS 8
(PARTITION P2020_Q1 VALUES LESS THAN("20200401")
PARTITION P2020_Q2 VALUES LESS THAN("20200701")
PARTITION P2020_Q3 VALUES LESS THAN("20201001")
PARTITION P2020_Q4 VALUES LESS THAN('20210101')
PETITION P2022_Q1 VALUES LESS THAN('20210401')
PARTITION P9999_MX VALUES LESS THAN (MAXVALUE));
SELECT * FROM 주문
WHERE 주문일자 BETWEEN 20201001 AND 20201231;
WHERE TO_NUMBER(주문일자) BETWEEN 20261001 AND 28201231
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일자)
(PARTITION P1 VALUES LESS THAN("20210201")
, PARTITION P2 VALUES LESS THAN("20210301")
, PARTITION P3 VALUES LESS THAN("20210401")
, PARTITION P4 VALUES LESS THAN("20210501")
, PARTITION P5 VALUES LESS THAN("20210601")
PARTITION PMX VALUES LESS THAN (MAXVALUE));
SELECT * FROM 주문
WHERE 주문일자 LIKE '20203%' ;
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일자 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일자)
(PARTITION P2020_Q1 VALUES LESS THAN("20200401")
, PARTITION P2020_Q2 VALUES LESS THAN("20200701")
, PARTITION P2020_Q3 VALUES LESS THAN("20201001")
, PARTITION P2020_Q4 VALUES LESS THAN('20210101')
, PETITION P2022_Q1 VALUES LESS THAN('20210401')
, PARTITION P9999_MX VALUES LESS THAN (MAXVALUE));
CREATE INDEX 주문_X1 ON 주문 (고객 ID) LOCAL ;
✅ Local 파티션 인덱스
- Local 파티션 인덱스는 테이블 파티션 속성을 그대로 상속받는다.
- 따라서 테이블 파티션 키가 주문일시면 인덱스 파티션 키도 주문일시가 된다.
- Local 파티션 인덱스를 'Local 인덱스'라고 줄여서 부르기도 한다.
- ⭐️Local 파티션 인덱스는 테이블과 정확히 1:1 대응 관계를 갖도록 오라클이 파티션을 자동으로 관리해 준다.⭐️
- ⭐️테이블 파티션 구성을 변경(add, drop, exchange 등)하더라도 인덱스를 재생성할 필요가 없다.⭐️
- 변경작업이 순식간에 끝나므로 피크(peak) 시간대만 피하면 서비스를 중단하지 않고도 작업할 수 있다.
- Local 파티션 인덱스의 장점은 이처럼 관리 편의성에 있다.
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일시 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일시)
(PARTITION Q1 VALUES LESS THAN (TO DATE('20200401", "YYYYMMDD"))
, PARTITION Q2 VALUES LESS THAN (TO DATE('20200701", "YYYYMMDD"))
, PARTITION Q3 VALUES LESS THAN (TO DATE('20201001", "YYYYMMDD"))
, PARTITION Q4 VALUES LESS THAN (TO DATE('20210101", "YYYYMMDD"))
, PARTITION QMAX VALUES LESS THAN ( MAXVALUE ) );
CREATE INDEX 주문_X1 ON 주문(주문일시, 고객ID) GLOBAL
PARTITION BY RANGE (주문일시)
(PARTITION P2020 VALUES LESS THAN( TO DATE('20200701','YYYMMDD'))
, PARTITION P2021 VALUES LESS THAN( TO DATE('20210101','YYYMMDD'))
, PARTITION P9999 VALUES LESS THAN( MAXVALUE));
✅ Global 파티션 인덱스
- Global 파티션 인덱스는 파티션을 테이블과 다르게 구성한 인덱스다.
- 구체적으로, 파티션 유형이 다르거나, 파티션 키가 다르거나, 파티션 기준값 정의가 다른 경우다.
- 비파티션 테이블이어도 인덱스는 파티셔닝할 수 있다.
- ⭐️글로벌 파티션 인덱스는 테이블 파티션 구성을 변경(DROP, EXCHANGE, SPLIT 등)하는 순간 Unusable 상태로 바뀌므로 곧바로 인덱스를 재생성해 줘야 한다.⭐️
- 그동안 해당 테이블을 사용하는 서비스를 중단해야 한다.
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일시 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일시)
(PARTITION Q1 VALUES LESS THAN (TO DATE('20200401", "YYYYMMDD"))
, PARTITION Q2 VALUES LESS THAN (TO DATE('20200701", "YYYYMMDD"))
, PARTITION Q3 VALUES LESS THAN (TO DATE('20201001", "YYYYMMDD"))
, PARTITION Q4 VALUES LESS THAN (TO DATE('20210101", "YYYYMMDD"))
, PARTITION QMAX VALUES LESS THAN ( MAXVALUE ) );
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일시 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일시) GLOBAL
(PARTITION Q1 VALUES LESS THAN (TO DATE('20200401", "YYYYMMDD"))
, PARTITION Q2 VALUES LESS THAN (TO DATE('20200701", "YYYYMMDD"))
, PARTITION Q3 VALUES LESS THAN (TO DATE('20201001", "YYYYMMDD"))
, PARTITION Q4 VALUES LESS THAN (TO DATE('20210101", "YYYYMMDD"))
, PARTITION QMAX VALUES LESS THAN ( MAXVALUE ) );
CREATE TABLE 주문 ( 주문번호 NUMBER, 주문일시 VARCHAR2(8), 고객ID VARCHAR2(5), - )
PARTITION BY RANGE (주문일시)
(PARTITION Q1 VALUES LESS THAN (TO DATE('20200401", "YYYYMMDD"))
, PARTITION Q2 VALUES LESS THAN (TO DATE('20200701", "YYYYMMDD"))
, PARTITION Q3 VALUES LESS THAN (TO DATE('20201001", "YYYYMMDD"))
, PARTITION Q4 VALUES LESS THAN (TO DATE('20210101", "YYYYMMDD"))
, PARTITION QMAX VALUES LESS THAN ( MAXVALUE ) );
CREATE UNIQUE INDEX 주문_PK ON 주문 (주문번호);
ALTER TABLE 주문 ADD CONSTRAINT 주문_PK PRIMARY KEY(주문번호) USING INDEX 주문_PK;
[테이블 구성 |
CREATE TABLE 거래
( 거래일자 VARCHAR2(8)
, 계좌번호 NUMBER
, 주문매체코드 VARCHAR2(2)
, 거래유형코드 VARCHAR2(4)
, 거래량 NUMBER
, 거래금액 NUMBER )
PARTITION BY RANGE (거래일자)
(PARTITION P2021_M01 VALUES LESS THAN ('20210201')
, PARTITION P2021_M02 VALUES LESS THAN ('20210301')
, ...
, ...
, PARTITION P9999_MX VALUES LESS THAN(MAXVALUE ) );
[튜닝 대상 SQL]
SELECT SUM(거래량), SUM(거래금액)
FROM 거래
WHERE 계좌번호 = :ACNT_NO
AND 거래일자 >= TO_CHAR(ADD_MONTHS(SYSDATE, -2), 'YYYYMMDD');
[테이블 구성 |
CREATE TABLE 거래
( 거래일자 VARCHAR2(8)
, 계좌번호 NUMBER
, 주문매체코드 VARCHAR2(2)
, 거래유형코드 VARCHAR2(4)
, 거래량 NUMBER
, 거래금액 NUMBER )
PARTITION BY RANGE (거래일자)
(PARTITION P2021_M01 VALUES LESS THAN ('20210201')
, PARTITION P2021_M02 VALUES LESS THAN ('20210301')
, ...
, ...
, PARTITION P9999_MX VALUES LESS THAN(MAXVALUE ) );
[튜닝 대상 SQL]
SELECT SUM(거래량), SUM(거래금액)
FROM 거래
WHERE 계좌번호 = :ACNT_NO;
을 고르시오
[테이블 구성 |
CREATE TABLE 거래
( 입금일자 VARCHAR2(8)
, 거래일시 DATE
, 계좌번호 NUMBER
, 주문매체코드 VARCHAR2(2)
, 거래유형코드 VARCHAR2(4)
, 거래량 NUMBER
, 거래금액 NUMBER )
PARTITION BY RANGE (거래일시)
(PARTITION Q1 VALUES LESS THAN (TO DATE('20200201", "YYYYMMDD"))
, PARTITION Q2 VALUES LESS THAN (TO DATE('20200301", "YYYYMMDD"))
, ...
, ...
, PARTITION P9999_MX VALUES LESS THAN(MAXVALUE ) );
CREATE UNIQUE INDEX 거래_PK ON 거래 (계좌번호, 거래일시) LOCAL;
ALTER TABLE 거래 ADD
CONSTRAINT 거래_PK PRIMARY KEY(계좌번호, 거래일시) USING INDEX 거래_PK;
[튜닝 대상 SQL ]
SELECT /*+ ORDERED USE_NL(B) */ *
FROM 계좌 A, 거래 B
WHERE A. 지점코드 = :BRCH_CD
AND B. 계좌번호 = A. 계좌번호
AND B. 입금일자 = :PAY_DT ;