Базы данных Oracle - статьи

         

Построение в рамках одной схемы: подмена запроса


Эта разновидность materialized view может создаваться только на основе таблицы, находящейся в той же схеме. Кроме этого, для ее создания нужно иметь особую привилегию QUERY REWRITE.

Подготовка примера

Выдадим от имени SYS:

GRANT QUERY REWRITE TO scott;

Построение примера

Выдадим в SQL*Plus от имени SCOTT:

CREATE MATERIALIZED VIEW dept_salaries ENABLE QUERY REWRITE AS SELECT dname, COUNT(emp.deptno) emp_count, SUM(sal) tot_sal FROM emp, dept WHERE emp.deptno (+) = dept.deptno GROUP BY dname;

(В следующем примере и в двух далее одинаковым фоном выделены одинаковые участки кода).

Выводимая таблица DEPT_SALARIES показывает список отделов, число работающих в них и фонд зарплаты. Число отделов:

SELECT COUNT(*) FROM dept_salaries;

Проверка работы переформулировки

Проанализируем таблицы (желательно) и сравним планы:

ANALYZE TABLE emp COMPUTE STATISTICS; ANALYZE TABLE dept COMPUTE STATISTICS; ANALYZE TABLE dept_salaries COMPUTE STATISTICS;

SET AUTOTRACE TRACEONLY EXPLAIN

SELECT dname, COUNT(emp.deptno) emp_count, SUM(sal) tot_sal FROM emp, dept WHERE emp.deptno (+) = dept.deptno GROUP BY dname;

ALTER SESSION SET QUERY_REWRITE_ENABLED=TRUE;

SELECT dname, COUNT(emp.deptno) emp_count, SUM(sal) tot_sal FROM emp, dept WHERE emp.deptno (+) = dept.deptno GROUP BY dname;

Два последних оператора SELECT идентичны.

Пример показывает, что мы можем продолжать работать с исходными таблицами независимо от того, построена выводимая таблица DEPT_SALARIES, или нет. СУБД сама определила, что таковая имеется, и переадресовала запрос к ней. Сама таблица DEPT_SALARIES не несет в себе новых данных и ее наличие, подобно наличию индекса, позволяет в некоторых случаях сократить время доступа к исходной информации.

Следующие примеры свидетельствуют, что для подобной автоматической переадресации к данным в приложении не обязательно повторять в точности формулировку имеющейся выводимой таблицы. Достаточно, чтобы в выводимой таблице с хранимым результатом хватало данных для ответа:

SELECT dname, COUNT(emp.deptno) emp_count FROM emp, dept WHERE emp.deptno (+) = dept.deptno GROUP BY dname;

SELECT dname, COUNT(emp.deptno) emp_count, SUM(sal) tot_sal FROM emp, dept WHERE emp.deptno (+) = dept.deptno AND dept.deptno <> 10 GROUP BY dname;



Содержание раздела