내용 목차
본 장에서는 Tibero에서 제공하는 실체화 뷰를 사용하는 방법에 대해 기술한다.
마스터 테이블에 변경이 일어났을 때 이를 반영하도록 실체화 뷰를 갱신하는 동작을 리프레시라고 한다. 리프레시를 하면 실체화 뷰의 데이터는 질의의 결과와 일치된다. 리프레시는 실체화 뷰를 생성하는 조건에 따라 자동으로 수행될 수 있으며, DBMS_MVIEW 패키지의 REFRESH 함수를 이용하여 수동으로 수행할 수도 있다.
리프레시는 완전 리프레시와 빠른 리프레시가 있다.
완전 리프레시는 실체화 뷰에 있는 기존의 데이터를 모두 삭제한 후 실체화 뷰를 정의한 질의를 다시 수행하여 그 결과를 실체화 뷰에 저장하는 방식이다. 완전 리프레시를 사용하기 위한 특별한 제약조건은 없다.
빠른 리프레시는 마스터 테이블의 변경된 부분만을 실체화 뷰에 반영하는 방식이다. 완전 리프레시보다 빠르다.
빠른 리프레시를 사용하기 위한 제약조건은 다음과 같다. 실체화 뷰를 정의하는 질의는 다음의 제약조건을 만족해야 한다.
실체화 뷰는 SYSDATE와 ROWNUM과 같이 반복할 수 없는 표현식을 포함하면 안 된다.
실체화 뷰는 LONG 또는 LONG RAW 데이터 타입을 포함하면 안 된다.
SELECT 리스트에 부질의를 포함하면 안 된다.
SELECT 리스트에 분석 함수를 포함하면 안 된다.
HAVING 절에 부질의를 포함하면 안 된다.
ANY, ALL, NOT EXISTS를 포함하면 안 된다.
[START WITH] CONNECT BY 절을 포함하면 안 된다.
서로 다른 원격에 있는 테이블을 포함하면 안 된다. 즉, 쿼리에 참가하는 모든 테이블은 같은 서버에 있어야 한다.
원격 테이블이 포함된 경우 해당 서버가 Tibero일 경우만 된다.
UNION 등의 SET 연산자를 포함하면 안 된다.
REFRESH ON COMMIT 실체화 뷰를 정의한 질의는 원격 테이블을 포함하면 안 된다.
다음은 집합 함수를 포함한 제약조건에 대한 설명이다.
빠른 리프레시의 일반적인 제약조건을 모두 포함한다.
실체화 뷰의 모든 참조 테이블에는 실체화 뷰의 로그가 있어야 하며, 실체화 뷰의 로그는 다음의 제약조건을 만족해야 한다.
실체화 뷰에서 참조하는 모든 컬럼을 포함해야 한다.
SEQUENCE, ROWID와 INCLUDING NEW VALUES 조건이 있어야 한다.
함수는 SUM, COUNT, AVG, STDDEV, VARIANCE. MIN, MAX 함수만 지원된다.
COUNT(*)는 항상 포함해야 한다.
집합 함수는 항상 표현식의 최상위에 있어야 한다. 단, AVG(COUNT(X)), COUNT(X) * COUNT(X)는 허용하지 않는다.
AVG(expr)에 대응되는 COUNT(expr)가 있어야 한다.
집단 함수 | 필요 집단 함수 |
---|---|
COUNT(expr) | - |
MIN(expr) | - |
MAX(expr) | - |
SUM(expr) | COUNT(expr) |
SUM(col), col에 NOT NULL 제약 | - |
AVG(expr) | COUNT(expr) |
STDDEV(expr) | SUM(expr), COUNT(expr) |
VARIANCE(expr) | SUM(expr), COUNT(expr) |
SELECT 리스트에는 모든 GROUP BY 컬럼이 있어야 한다.
CUBE, ROLLUP은 허용하지 않는다.
실체화 뷰의 가장 큰 장점은 질의 다시 쓰기(Query Rewrite) 기능을 사용할 수 있다는 것이다.
질의 다시 쓰기는 주어진 질의를 분석한 후 실체화 뷰를 사용하여 동일한 결과를 내는 새로운 질의를 생성하는 기능이다. 실체화 뷰가 복잡한 조인이나 집단 함수의 결과로 정의되어 있다면 질의 다시 쓰기를 통해 실행 시간을 크게 단축할 수 있다.
질의 다시 쓰기는 사용자가 명시한 명령 없이도 질의 최적화기에 의해 수행되므로 실체화 뷰를 인덱스처럼 사용할 수 있다. INSERT, DELETE, UPDATE, MERGE의 대상이 되는 부질의를 제외한 모든 SELECT 문에 동작한다.
EXPLAIN PLAN 문을 통해서 실행 계획을 보면 질의 다시 쓰기에 의해 참조된 실체화 뷰는 MV_REWRITE라고 표시된다.
질의 다시 쓰기 기능을 동작하기 위한 조건은 다음과 같다.
실체화 뷰를 생성할 때 ENABLE QUERY REWRITE 옵션을 추가해야 한다.
QUERY_REWRITE_ENABLED 파라미터의 값이 TRUE나 FORCE로 설정되어 있어야 한다.
QUERY_REWRITE_ENABLED = {TRUE | FORCE}
질의 다시 쓰기가 QUERY_REWRITE_INTEGRITY 파라미터의 설정을 만족시켜야 한다.
QUERY_REWRITE_INTEGRITY = {ENFORCED | STALE_TOLERATED}
QUERY_REWRITE_INTEGRITY 파라미터는 다음의 설정 값을 통해 질의 다시 쓰기의 정확도를 조절할 수 있다.
설정 값 | 설명 |
---|---|
ENFORCED | 최신 데이터가 있는 실체화 뷰만 사용하여 원본 질의와 동일한 결과를 보장한다. |
STALE_TOLERATED | 최신 데이터의 변경 내용이 반영되지 않은 실체화 뷰를 사용하기 때문에 원본 질의와 동일한 결과를 보장하지 않는다. 단, 질의 다시 쓰기가 될 가능성은 커진다. |
질의 다시 쓰기를 하려면 원본 질의와 사용할 실체화 뷰의 질의를 비교해서 원본 질의가 실체화 뷰를 사용해서 얻어질 수 있는지를 확인해야 한다. 현재는 완전 문자열 비교와 부분 문자열 비교 방식을 지원한다.
원본 질의와 사용할 실체화 뷰의 질의에 대해 전체 문자열을 비교한다. 이때 공백이나 대소문자의 차이는 무시된다.
예를 들어 다음과 같은 실체화 뷰가 있다고 가정해 보자.
CREATE MATERIALIZED VIEW MV_SUM_SALARY ENABLE QUERY REWRITE AS SELECT DNAME, SUM(SALARY) FROM DEPT, EMP WHERE DEPT.DEPTNO = EMP.DEPTNO GROUP BY DNAME;
다음과 같은 질의를 실행한다면,
SELECT dname, SUM(salary) FROM dept,emp WHERE DEPT.DEPTNO = EMP.DEPTNO GROUP BY dname;
다음과 같이 질의 다시 쓰기가 동작하게 된다.
SELECT * FROM MV_SUM_SALARY;
원본 질의와 사용할 실체화 뷰의 질의에 대해 FROM 절부터 ORDER BY 절 앞까지(존재할 경우)의 문자열을 비교하고, SELECT 리스트와 ORDER BY 절의 연산식에서 사용되는 컬럼의 적합성을 조사한다.
원본 질의의 SELECT 리스트 컬럼이 실체화 뷰의 컬럼을 조합해서 얻어질 수 있는지를 검사한다. 이때 조인에 의해 같아지는 컬럼을 처리한다.
예를 들어 다음과 같은 실체화 뷰가 있다고 가정해 보자.
CREATE MATERIALIZED VIEW MV_JOIN_DEPT_EMP ENABLE QUERY REWRITE AS SELECT ENAME, DNAME, DEPT.DEPTNO FROM DEPT, EMP WHERE DEPT.DEPTNO = EMP.DEPTNO;
다음과 같은 질의를 실행한다면,
SELECT ENAME, DNAME, EMP.DEPTNO FROM DEPT, EMP WHERE DEPT.DEPTNO = EMP.DEPTNO;
다음과 같이 질의 다시 쓰기가 동작하게 된다.
SELECT ENAME, DNAME, DEPTNO FROM MV_JOIN_DEPT_EMP;
또한, 연산의 교환, 결합, 분배 법칙을 이용하여 동등한 연산식의 컬럼을 처리한다.
예를 들어 다음과 같은 실체화 뷰가 있다고 가정해 보자.
CREATE MATERIALIZED VIEW mymv ENABLE QUERY REWRITE AS SELECT a*(c+4)+b c1, sum(c+a)+1 c2 FROM base GROUP BY a*(c+4)+b, b+4*a+a*c;
다음과 같은 질의를 실행한다면,
SELECT b+4*a+a*c+(1+sum(a+c))*7 FROM base GROUP BY a*(c+4)+b, b+4*a+a*c;
다음과 같이 질의 다시 쓰기가 동작하게 된다.
SELECT c1+c2*7 FROM mymv;
집단 함수를 사용할 때 집단 함수의 적합성을 조사하는 방법은 다음과 같다.
해당되는 집단 함수가 없어도 다른 집단 함수를 조합하여 원하는 집단 함수를 얻을 수 있다. 예를 들어 AVG(SALARY)는 SUM(SALARY) / COUNT(SALARY)로 구할 수 있다.
다음은 집단 함수의 적합성을 조사한 표이다.
목표 집단 함수 | 필요 집단 함수 |
---|---|
AVG(expr) | SUM(expr), COUNT(expr) |
SUM(expr) | AVG(expr), COUNT(expr) |
STDDEV(expr) | VARIANCE(expr) |
(STDDEV_SAMP(expr), STDDEV_POP(expr), VAR_SAMP(expr), VAR_POP(expr)) 중 하나, COUNT(expr) | |
SUM(expr * expr), SUM(expr), COUNT(expr) | |
STDDEV_SAMP(expr) | VAR_SAMP(expr) |
(STDDEV(expr), STDDEV_POP(expr), VARIANCE(expr), VAR_POP(expr)) 중 하나, COUNT(expr) | |
SUM(expr * expr), SUM(expr), COUNT(expr) | |
STDDEV_POP(expr) | VAR_POP(expr) |
(STDDEV(expr), STDDEV_SAMP(expr), VARIANCE(expr), VAR_SAMP(expr)) 중 하나, COUNT(expr) | |
SUM(expr * expr), SUM(expr), COUNT(expr) | |
VARIANCE(expr) | STDDEV(expr) |
(STDDEV_SAMP(expr), STDDEV_POP(expr), VAR_SAMP(expr), VAR_POP(expr)) 중 하나, COUNT(expr) | |
SUM(expr * expr), SUM(expr), COUNT(expr) | |
VAR_SAMP(expr) | STDDEV_SAMP(expr) |
(STDDEV(expr), STDDEV_POP(expr), VARIANCE(expr), VAR_POP(expr)) 중 하나, COUNT(expr) | |
SUM(expr * expr), SUM(expr), COUNT(expr) | |
VAR_POP(expr) | STDDEV_POP(expr) |
(STDDEV(expr), STDDEV_SAMP(expr), VARIANCE(expr), VAR_SAMP(expr)) 중 하나, COUNT(expr) | |
SUM(expr * expr), SUM(expr), COUNT(expr) |
이기종 데이터베이스에서 실체화 뷰를 이용하여 Tibero에 있는 베이스 테이블의 데이터를 동기화하고 싶을 때 사용하는 기능이다.
이기종 데이터베이스에서 Tibero에 있는 베이스 테이블를 조회하는 실체화 뷰를 생성해도 빠른 리프레시는 수행이 불가능하다. 따라서 이 기능을 통해 실체화 뷰 관리를 Tibero쪽 데이터베이스가 담당하게 하고, 실제 저장소는 이기종 데이터베이스에 위치하게 하여 조회가 가능하게 한다. 현재 이기종 데이터베이스는 Oracle만 지원한다.
아래 설명을 하기 전에 베이스 테이블이 위치한 데이터베이스를 A, 실체화 뷰 저장소 테이블이 위치할 오라클 서버를 B이라 가정한다.
실체화 뷰 생성에 하기 전에 아래와 같은 사전 작업이 필요하다. 베이스 테이블이 위치한 데이터베이스를 A, 실체화 뷰 저장소 테이블이 위치할 오라클 서버를 B이라 가정한다.
B의 해당 계정에 Tibero에서 제공하는 $TB_HOME/scripts/mview_remote_install.sql 스크립트를 수행하여 기능에 필요한 PSM 패키지를 설치한다.
A에서 B로의 데이터베이스 링크를 생성한다.
PREBUILT 옵션만 지원하므로, 저장소 테이블을 사전에 생성한다.
A에서 실체화 뷰를 생성하지만, 실제 조회가 가능한 저장소 테이블은 B에 있다.
CREATE MATERIALIZED VIEW를 생성할 때 AT dblink_name 속성을 추가하여, A에서 B로의 데이터베이스 링크를 지정한다. 정확한 문법은 “7.41. CREATE TABLE”을 참고한다.
실체화 뷰 리프레시는 A에서 수행한다. 리프레시가 된 결과는 B의 저장소 테이블에 저장된다. 그 외의 사항에 대해서는 일반 실체화 뷰와 동일하다.