매번 View에 정의된 쿼리를 실행하는 일반 뷰(View)와는 달리 스냅샷(Snapshot)이라고 불리는 Materialized View(이하 M-view)는 쿼리 결과를 별도의 공간에 저장하고, 쿼리가 실행될때 미리 저장된 결과를 보여줌으로써 성능을 향상시켜 준다.
또한 일반 View와 마찬가지로 'Refresh Time'을 지정함으로써 실시간 데이터도 확인할 수 있다. 하지만 성능 향상을 위해 사용한 M-view가 오히려 성능저하의 원인이 될 수도 있다.
앞에서 언급한 것처럼 원본 테이블에 쿼리를 수행해 결과를 출력하는 방식이 아니라 M-view는 별도의 저장 공간을 가지고 쿼리의 결과를 미리 저장하는 방식이므로 실시간으로 데이터를 보여줄 필요가 적은 통계성 쿼리나 자주 update되지 않는 테이블에 M-view를 생성하는 것이 일반적이다.
만약 원본 테이블에 대량의 DML이 발생한다면, 이 DML이 원본 테이블 이외에도 모두 M-view에 순차적으로 반영되어야 해서 많은 시간이 소요되므로 M-View로 인해 성능저하가 발생할 수 있기 때문이다.
또한 업무 특성을 고려하지 않고 원본 테이블에 이미 쿼리의 결과가 저장되어 있으므로 빠른 성능을 기대해 M-view를 생성 했다면 오히려 성능을 더 악화시킬 수 있다.
-- 테이블 생성
CREATE TABLE TEST1 AS
SELECT LEVEL COL1, MOD(LEVEL, 5) COL2
FROM DUAL
CONNECT BY LEVEL <= 1000000
/
-- COL2에 인덱스 생성
CREATE INDEX TEST1_IDX ON TEST1(COL2, COL1)
/
-- M-VIEW LOG 생성
CREATE MATERIALIZED VIEW LOG ON TEST1 WITH ROWID
INCLUDING NEW VALUES
/
-- M-VIEW 생성
CREATE MATERIALIZED VIEW MVIEW_TEST1
BUILD IMMEDIATE
REFRESH FAST ON COMMIT WITH ROWID
ENABLE QUERY REWRITE AS (
SELECT COL1, COL2
FROM TEST1
WHERE COL2 in ( '1','2','3') ) ;
-- 개발자의 의도는 100만 건의 데이터 중 30%에 해당되는 데이터만을 SELECT 할
경우를위해서 M-view를 생성해 속도를 향상시키는 것이다.
-- M-view를 이용한 Data 추출
SELECT *
FROM MVIEW_TEST1
WHERE COL1 IN ('1', '2', '3');
Call Count CPU Time Elapsed Time Disk Query Current Rows
----- ------ -------- ------------ ---- ----- ------ -----
Parse 1 0.031 0.059 0 70 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.063 0.074 0 2219 0 3
Total 4 0.094 0.133 0 2289 0 3
Misses in library cache during parse: 1
Optimizer goal: ALL_ROWS
Parsing user: SYSTEM (ID=5)
Rows Row Source Operation
---------------------------------------------------
0 STATEMENT
3 MAT_VIEW ACCESS FULL MVIEW_TEST1 (cr=2219 pr=0pw=0 time=50 us)
실제 쿼리가 들어오는 Access pattern은 MVIEW_TEST1 데이터 중 col1의 값을 추출하는 쿼리가 대부분이었다.
M-View에 Index가 생성되어 있지 않으므로 M-View의 Full Scan이 발생해 총 '2289'블록을 Access 했다.
-- 일반 View 생성
CREATE OR REPLACE VIEW VIEW_TEST1
AS
SELECT COL1, COL2
FROM TEST1
WHERE COL2 in ('1','2','3')
/
-- 일반 View를 이용한 Data 추출
SELECT *
FROM VIEW_TEST1
WHERE COL1 IN ('1','2','3')
/
Call Count CPU Time Elapsed Time Disk Query Current Rows
----- ------ -------- ------------ ---- ----- ------ -----
Parse 1 0.000 0.031 0 0 0 0
Execute 1 0.000 0.000 0 0 0 0
Fetch 2 0.016 0.000 0 28 0 3
Total 4 0.016 0.032 0 28 0 3
Misses in library cache during parse: 0
Optimizer goal: ALL_ROWS
Parsing user: SYSTEM (ID=5)
Rows Row Source Operation
---------------------------------------------------
0 STATEMENT
3 INLIST ITERATOR (cr=28 pr=0 pw=0 time=31 us)
3 INDEX RANGE SCAN TEST1_IDX (cr=28 pr=0 pw=0time=77 us)(Object ID 52555)
일반 View는 실제 원본 Table에 Query를 실행하므로 COL2+COL1으로 구성된 TEST1_IDX를 이용해 '28'블록만 Access했다.
이처럼 업무의 특성은 고려하지 않고 원본 테이블보다 적은 양의 Data Block을 Access하므로 (100만 블록의 30%만 M-view에 저장되므로) 성능 향상을 이유로 M-view를 생성했다면 성능을 더 악화시킬 뿐이다.
또한 이 Table이 실시간으로 많은 트랜잭션을 발생시키는 테이블이라면 원본 테이블과 더불어 M-view 테이블도 실시간으로 트랜잭션을 반영해야 하므로 더 안 좋은 성능을 초래할 뿐이다.
위와 같이 변경된 데이터를 실시간으로 보여줘야 되고, DML이 많이 발생하는 테이블이라면 차라리 일반 View를 생성하는 것이 더 효과적일 수 있다.
- 강좌 URL : http://www.gurubee.net/lecture/2638
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.