이번 글에서는 FBI(Function-Based Index)의 활용 사례를 살펴보자.
테스트를 위해 아래와 같이 테이블을 생성하자. c2 열의 값은 대부분 N이다.
-- 1 DROP TABLE t1 PURGE; CREATE TABLE t1 AS SELECT ROWNUM AS c1 , CASE WHEN ROWNUM IN (1, 1000000) THEN 'Y' ELSE 'N' END AS c2 , LPAD ('X', 100, 'X') AS c3 FROM XMLTABLE ('1 to 1000000');
아래가 성능 개선이 필요한 쿼리다. t1 테이블을 전체 스캔하여 15,629개의 블록 I/O가 발생했다.
-- 2 SELECT MAX (c1) FROM t1 WHERE c2 = 'Y'; --------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | Buffers | --------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1 | 15629 | | 1 | SORT AGGREGATE | | 1 | 1 | 15629 | |* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 15629 | ---------------------------------------------------------------
간단한 해법은 아래처럼 t1_x1 인덱스를 생성하는 것이다. 블록 I/O가 3으로 감소한 것을 확인할 수 있다. 하지만 t1 테이블의 크기가 큰 경우 인덱스의 추가가 어려울 수 있다.
-- 3 CREATE INDEX t1_x1 ON t1 (c2, c1); SELECT MAX (c1) FROM t1 WHERE c2 = 'Y'; -------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | Buffers | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1 | 3 | | 1 | SORT AGGREGATE | | 1 | 1 | 3 | | 2 | FIRST ROW | | 1 | 1 | 3 | |* 3 | INDEX RANGE SCAN (MIN/MAX)| T1_X1 | 1 | 1 | 3 | --------------------------------------------------------------------------
이런 경우 아래와 같이 FBI를 활용할 수 있다. t1_x2 인덱스에는 c2가 Y인 행만 저장되므로 관리와 성능 측면에서 t1_x1 인덱스에 비해 유리하다.
-- 4 CREATE INDEX t1_x2 ON t1 (DECODE (c2, 'Y', c1)); SELECT MAX (DECODE (c2, 'Y', c1)) FROM t1; ------------------------------------------------------------------------ | Id | Operation | Name | Starts | A-Rows | Buffers | ------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 1 | 1 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 | | 2 | INDEX FULL SCAN (MIN/MAX)| T1_X2 | 1 | 1 | 1 | ------------------------------------------------------------------------
아래는 t1_x1, t1_x2 인덱스 정보를 조회한 결과다.
-- 5 SELECT index_name, index_type, blevel, leaf_blocks FROM user_indexes WHERE table_name = 'T1'; INDEX_NAME INDEX_TYPE BLEVEL LEAF_BLOCKS ---------- --------------------- ------ ----------- T1_X1 NORMAL 2 2505 T1_X2 FUNCTION-BASED NORMAL 0 1 2 행이 선택되었습니다.
'Oracle > Tuning' 카테고리의 다른 글
중복 표현식 (0) | 2019.10.02 |
---|---|
병렬 쿼리 평균 수행 시간 (0) | 2019.10.01 |
DUAL CONNECT BY 쿼리 성능 개선 방안 (0) | 2019.09.11 |
UPDATE 문 성능 개선 사례 (0) | 2019.09.03 |
NO FPD 뷰 성능 개선 방안 (0) | 2019.09.02 |