Май 2005


Тема номера: Аналитические системы и хранилища данных


Аруп Нанда

Камера наилучшего видения
(Room with a Better View, by Arup Nanda)

Источник: журнал Oracle Magazine, no.2, 2005, Раздел “ТЕХНОЛОГИИ: Хранилище данных”, http://www.oracle.com/technology/oramag/oracle/05-mar/o25data.html

Взгляните на свои данные через материализованные представления.

Пользователи Acme Bank жаловались, что повторяющиеся стандартные запросы слишком долго выполняются. Поскольку эти запросы выполнялись многими пользователями снова и снова, любое улучшение времени отклика было бы полезно.

Администраторы базы данных Acme Bank настроили наиболее часто используемые запросы, все необходимые индексы существовали, и никакая дополнительная SQL настройка не вносила никаких изменений в выполнение этих запросов.

Решение администраторов БД Acme Bank: использовать материализованные представления (materialized views).

В этой статье обсуждается: как планировать материализованные представления; как настраивать и использовать их различные возможности; как автоматически генерировать скрипты для создания материализованных представлений; как сделать доступной возможность переписывания запроса (query rewrite); и как убедиться, что эта возможность используется.

От запросов к представлениям

Вот распространенный запрос в Acme Bank:

SELECT acc_type, SUM(cleared_bal) totbal
FROM accounts
GROUP BY acc_type;

А вот материализованное представление для этого запроса - mv_bal:

CREATE OR REPLACE MATERIALIZED VIEW mv_bal
REFRESH ON DEMAND AS
SELECT acc_type, SUM(cleared_bal) totbal
FROM accounts
GROUP BY acc_type;

Материализованные представления – это сегменты, похожие на таблицы, хранящие результаты запросов в базе данных.

Предположим теперь, что пользователь хочет получить сумму всех остатков на счетах для типа счета 'C' и выполняет следующий запрос:

SELECT SUM(cleared_bal)
FROM accounts
WHERE acc_type = 'C';

Поскольку материализованное представление mv_bal уже содержит все суммы по типам счетов, пользователь может получить эту информацию непосредственно из материализованного представления, выполнив следующий запрос:

SELECT totbal
FROM mv_bal
WHERE acc_type = 'C';

Этот запрос к материализованному представлению mv_bal вернет результаты значительно быстрее, чем запрос непосредственно к таблице accounts. Выполнение запроса к материализованному представлению будет быстрее, чем выполнение исходного запроса, потому что при запросе к материализованному представлению не происходит обращения к исходной таблице.

Но есть и другое различие между запросом к исходной таблице и к материализованному представлению. Когда пользователь выполняет запрос к исходной таблице, в качестве результата возвращаются текущие данные. В то время как запрос к материализованному представлению возвращает данные, актуальные на момент создания материализованного представления. И поскольку материализованное представление не обновляется, когда обновляются данные в исходной таблице, необходимо выполнять синхронизацию.

Чтобы поддерживать актуальность данных, материализованное представление должно время от времени обновляться, вручную или автоматически. Существует два способа обновления данных в материализованном представлении. Один из них заключается в том, что материализованное представление полностью очищается и затем вновь заполняется данными из исходных таблиц – этот процесс известен как полное обновление. Однако, в некоторых случаях, когда исходные таблицы меняются очень незначительно, можно обновлять материализованное представление только для измененных записей исходных таблиц – этот процесс называется быстрое обновление. Чтобы использовать быстрое обновление необходимо создать материализованное представление как быстро-обновляемое (fast-refreshable). Поскольку обновляются только измененные записи, быстрое обновление выполняется быстрее, чем полное обновление (Подробнее об обновлении материализованных представлений смотри в Oracle Database Data Warehousing Guide).

Чтобы быть уверенным, что пользователи будут использовать материализованные представления Acme Bank, даже если они ничего не знают о них, в банке используется возможность переписывания запросов. Благодаря возможности переписывания запросов машина базы данных может автоматически переписывать исходный запрос от пользователя так, чтобы использовать материализованное представление, поэтому пользователь не должен знать обо всех существующих материализованных представлениях. В некоторых случаях, например в OLTP системе, запрос к материализованным представлениям может быть нежелателен, поскольку они могут не содержать актуальных данных из исходных таблиц. В таких случаях возможность переписывания запросов может быть отключена – либо на уровне базы данных, либо для конкретной сессии, либо только для отдельных материализованных представлений.

Администратор БД может включить возможность переписывания запросов для сессии или для всей системы, установив значение параметра QUERY_REWRITE_INTEGRITY в true. Чтобы материализованное представление могло быть использовано при переписывании запросов, оно должно быть создано с предложением ENABLE QUERY. Например, следующий код создает для сложного запроса Acme Bank, представленного в Листинге 1, материализованное представление acc_mgr_view с возможностью его использования при переписывании запросов:

CREATE OR REPLACE MATERIALIZED VIEW
acc_mgr_view
ENABLE QUERY REWRITE AS
<запрос, представленный в Листинге 1>
/

Код Листинга 1: Исходный запрос

select acc_mgr_id,
   acc_type_desc,
   decode
      (a.sub_acc_type,null,'?', sub_acc_type_desc)
                                  		sub_acc_type_desc,
   sum(cleared_bal)               		tot_cleared_bal,
   sum(uncleared_bal)             		tot_uncleared_bal,
   avg(cleared_bal)               		avg_cleared_bal,
   avg(uncleared_bal)             		avg_uncleared_bal,
   sum(cleared_bal+uncleared_bal) 	tot_total_bal,
   avg(cleared_bal+uncleared_bal) 	avg_total_bal,
   min(cleared_bal+uncleared_bal) 	min_total_bal
from balances b,
   accounts a,
   acc_types at,
   sub_acc_types sat
where a.acc_no = b.acc_no
and at.acc_type = a.acc_type
and sat.sub_acc_type (+) = a.sub_acc_type
group by  acc_mgr_id, acc_type_desc,
   decode
      (a.sub_acc_type,null,'?', sub_acc_type_desc)

Оценка памяти

Преобразовать запрос, представленный в Листинге 1, в материализованное представление легко, но существует несколько вопросов, на которые необходимо ответить перед его созданием, в том числе следующие: сколько памяти оно займет, и сколько строк будет содержать.

Пакет БД DBMS_MVIEW в Oracle 10g поможет ответить на эти вопросы. Чтобы оценить размер предполагаемого материализованного представления скрипт в Листинге 2 вызывает процедуру DBMS_MVIEW.ESTIMATE_MVIEW_SIZE.

Код Листинга 2: Оценка размера материализованного представления

set serveroutput on size 999999
declare
   l_num_rows  number;
   l_num_bytes number;
   l_stmt      varchar2(2000);
begin
   l_stmt := 'select acc_mgr_id,
      <the query shown in Listing 1>
      (a.sub_acc_type,null,''?'', sub_acc_type_desc)';
   dbms_mview.estimate_mview_size
   (
      stmt_id       => 'Est1',
      select_clause => l_stmt,
      num_rows      => l_num_rows,
      num_bytes     => l_num_bytes
   );
   dbms_output.put_line('Number of rows = '||l_num_rows);
   dbms_output.put_line('Size (bytes) = '||l_num_bytes);
end;
/

Количество строк = 2829000
Размер (в байтах) = 667644000

Результат в Листинге 2 показывает, что материализованное представление будет содержать 2,829,000 строк и займет около 667MB памяти. Эти приближенные значения вычисляются на основе статистики оптимизатора, собранной ранее для исходных таблиц, и точные значения могут быть другими. Но это помогает планировать память и определить, в какое табличное пространство поместить данное материализованное представление.

Проверка возможностей

Процедура DBMS_MVIEW.EXPLAIN_MVIEW проверяет возможности и характеристики материализованного представления до его создания и записывает результаты в таблицу MV_CAPABILITIES_TABLE. Сначала администратор БД должен создать эту таблицу, запустив скрипт utlxmv.sql, который находится в каталоге rdbms/admin под Oracle Home.

Листинг 3 использует процедуру DBMS_MVIEW.EXPLAIN_MVIEW, чтобы посмотреть, для каких типов операций предполагаемое материализованное представление можно будет использовать.

В первой части Листинга 3 таблица MV_CAPABILITIES_TABLE заполняется результатами, во второй части (после комментария – Теперь проверим возможности) данные выбираются из этой таблицы, как показано в запросе SELECT ROWNUM, CAPABILITY_NAME, .... Чтобы разобраться в полученных объяснениях, запрос использует ROWNUM для вывода номеров строк.

Код листинга 3: Проверка возможностей


declare
   l_stmt      varchar2(2000);
begin
   l_stmt := 'select acc_mgr_id,
       <the query shown in Listing 1>
      (a.sub_acc_type,null,''?'', sub_acc_type_desc)';
   dbms_mview.explain_mview
   (
      stmt_id => 'MV_Tune1',
      mv      => l_stmt
   );
end;
/
--
-- Now check the capabilities
--
SELECT ROWNUM, CAPABILITY_NAME, POSSIBLE, MSGTXT, RELATED_TEXT
FROM mv_capabilities_table
WHERE STATEMENT_ID = 'Est1'
AND CAPABILITY_NAME LIKE 'REFRESH%'
ORDER BY SEQ
/
-- Output
--
 LN    CAPABILITY_NAME                            P     MSGTXT                                     RELATED_TEXT    
---    --------------------------------------     --    ---------------------------------          ------------------- 
  1    REFRESH_COMPLETE                           Y 
  2    REFRESH_FAST                               N 
  3    REFRESH_FAST_AFTER_INSERT                  N     agg(expr) requires                          AVG_CLEARED_BAL 
                                                        correspondingCOUNT(expr) 
                                                        function                              
  4    REFRESH_FAST_AFTER_INSERT                  N     one or more joins present 
                                                        in mv                   
  5    REFRESH_FAST_AFTER_INSERT                  N     GROUP BY clause in mv 
  6    REFRESH_FAST_AFTER_INSERT                  N     aggregate function in mv 
  7    REFRESH_FAST_AFTER_INSERT                  N     the detail table does not                  ARUP.SUB_ACC_TYPES
                                                        not have a materialized 
                                                        view log            
  8    REFRESH_FAST_AFTER_ONETAB_DML              N     SUM(expr) without                          TOT_TOTAL_BAL   
                                                        COUNT(expr)
  9    REFRESH_FAST_AFTER_ONETAB_DML              N     SUM(expr) without                          TOT_UNCLEARED_BAL 
                                                        COUNT(expr)
 10    REFRESH_FAST_AFTER_ONETAB_DML              N     SUM(expr) without                          TOT_CLEARED_BAL 
                                                        COUNT(expr)
 11    REFRESH_FAST_AFTER_ONETAB_DML              N     see the reason why 
                                                        REFRESH_FAST_AFTER_INSERT 
                                                        is disabled 
 12   REFRESH_FAST_AFTER_ANY_DML                  N     see the reason why 
                                                        REFRESH_FAST_AFTER_ONETAB_DML 
                                                        is disabled 
 13    REFRESH_FAST_PCT                           N     PCT is not possible on any 
                                                        of the detail tables in the 
                                                        materialized view 

Результаты, приведенные в Листинге 3, рассказывают целую историю. В столбце CAPABILITY_NAME перечислены различные возможности обновления, а в столбце POSSIBLE (P) через простое Y (да) или N (нет) показывается, доступна ли эта возможность для данного материализованного представления. Материализованное представление может быть полностью обновлено, как показано в строке 1, но его нельзя быстро обновить, как показано в строке 2. Почему нет? Администратор БД просматривает список дальше, чтобы увидеть, почему недоступны возможности, связанные с обновлением. Строка 3 показывает, что быстрое обновление невозможно, потому что материализованное представление не имеет выражения COUNT() в запросе, в котором используются групповые функции, такие как SUM(). Если материализованное представление использует групповые функции, то в запросе должен присутствовать COUNT() , чтобы представление, основанное на этом запросе, можно было быстро обновлять. В столбце RELATED_TEXT показывается, на какие столбцы материализованного представления ссылается столбец MSGTXT. Данные столбца MSGTXT в строке 3 — agg(expr)(сокращение для aggregation(expression) – групповая функция (выражение)) — ссылаются на столбец AVG_CLEARED_BAL материализованного представления. Поскольку в запросе для построения материализованного представления используется выражение AVG(CLEARED_BAL), должно дополнительно существовать выражение COUNT(CLEARED_BAL) или COUNT(*), чтобы материализованное представление можно было быстро обновлять.

Кроме того, быстрое обновление требует создания журналов материализованного представления на базовые таблицы. В журналы записываются изменения, происходящие в базовых таблицах. Во время быстрого обновления процесс обновления просматривает эти журналы, чтобы определить, какие изменения необходимо выполнить в материализованном представлении. В строке 7 в столбце MSGTXT указано: the detail table does not have a materialized view log (детальная таблица не имеет журнала материализованного представления), а в столбце RELATED_TEXT показана таблица, для которой не существует журналов материализованного представления, —ARUP.SUB_ACC_TYPES.

Генерация скриптов

После того как администраторы БД Acme Bank использовали информацию Листинга 3, чтобы сделать планируемое материализованное представление, доступным для быстрого обновления, пришло время сгенерировать файл, который будет его создавать. Процедура, представленная в Листинге 4, задает имя задания и передает его и SQL запрос (из Листинга 1) процедуре DBMS_ADVISOR.TUNE_MVIEW, чтобы сгенерировать все необходимые SQL операторы для создания материализованного представления. После того как администратор БД выполнит скрипт, приведенный в Листинге 4, запуск следующего скрипта сгенерирует рекомендации DBMS Advisor:

CREATE DIRECTORY TMP_DIR AS '/tmp'
/

BEGIN
   DBMS_ADVISOR.CREATE_FILE (
      DBMS_ADVISOR.GET_TASK_SCRIPT 
         ('MV_Tune_Task1'),
   'TMP_DIR', 'mv_tune_task1.sql'
);
END;

Код Листинга 4: Генерация скриптов

declare
   l_stmt               varchar2(2000);
   l_task_name        varchar2(30);
begin
   l_task_name := 'MV_Tune_Task1';
   l_stmt        := 'create materialized view acc_mgr_view
                       enable query rewrite as
                       ... <the query shown in Listing 1>...';
   dbms_advisor.tune_mview
   (
      task_name        => l_task_name,
      mv_create_stmt => l_stmt
   );
end;
/

В результате создается файл mv_tune_task1.sql в каталоге /tmp, который содержит SQL операторы, необходимые для создания журналов материализованного представления на все базовые таблицы и самого материализованного представления со всеми соответствующими параметрами, которые нужны, чтобы его можно было быстро обновлять. После выполнения файла mv_tune_task1.sql в SQL*Plus все необходимые объекты будут созданы. Файл mv_tune_task1.sql приведен в Листинге 8.

Подтверждение переписывания запроса (Query Rewrite)

Листинг 5 содержит другой популярный пользовательский запрос в Acme Bank; он использует таблицы, столбцы и функцию, аналогичные существующим в запросе материализованного представления acc_mgr_view. Листинг 5 также использует возможность AUTOTRACE, имеющуюся в SQL*Plus, чтобы предоставить информацию о том, применяется ли переписывание запроса при выполнении запроса. Результат, выданный AUTOTRACE, ясно показывает, что запрос использует все исходные таблицы, а не материализованное представление acc_mgr_view. Почему?

Код листинга 5: Подтверждение переписывания запроса


SQL> alter session set query_rewrite_enabled = true;
Session altered.

SQL> set autotrace traceonly explain
SQL> select acc_type_desc, sum(cleared_bal)
  2   from balances b, accounts a, acc_types at
  3     where a.acc_no = b.acc_no
  4     and at.acc_type = a.acc_type
  5   group by acc_type_desc;

Execution Plan
--------------------------------------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=533 Card=4 Bytes=112)
   1    0   SORT (GROUP BY) (Cost=533 Card=4 Bytes=112)
   2    1     HASH JOIN (Cost=523 Card=50000 Bytes=1400000)
   3    2       HASH JOIN (Cost=146 Card=50000 Bytes=850000)
   4    3         TABLE ACCESS (FULL) OF 'ACC_TYPES' (TABLE) (Cost=3 Card=4 Bytes=40)
   5    3         TABLE ACCESS (FULL) OF 'ACCOUNTS' (TABLE) (Cost=140 Card=100000 Bytes=700000)
   6    2       TABLE ACCESS (FULL) OF 'BALANCES' (TABLE) (Cost=106 Card=100000 Bytes=1100000)

Запуск скрипта utlxrw.sql, находящегося в каталоге $ORACLE_HOME/rdbms/admin, создает таблицу REWRITE_TABLE, данные которой помогут определить, почему в запросе, приведенном в Листинге 5, оптимизатор не использует переписывание запроса. Выполнение процедуры DBMS_VIEW.EXPLAIN_REWRITE, как показано в Листинге 6, заполняет таблицу REWRITE_TABLE полученными данными. Запрос столбца MESSAGE таблицы REWRITE_TABLE позволяет найти причину:

SQL> SELECT MESSAGE FROM
REWRITE_TABLE;

QSM-01110: a lossy join in MV, 
ACC_MGR_VIEW, between tables, ACCOUNTS and SUB_ACC_TYPES, not found in query

Код Листинга 6: Проверка переписывания запроса

truncate table rewrite_table
/

declare
   l_stmt          varchar2(2000);
   l_task_name   varchar2(30);
begin
   l_stmt := 'select 
       acc_type_desc,
       sub_acc_type,
       sum(cleared_bal)  
from 
   balances b, 
   accounts a, 
   acc_types at
where 
   a.acc_no = b.acc_no
and 
   at.acc_type = a.acc_type
group by 
   acc_type_desc, sub_acc_type';

   dbms_mview.explain_rewrite
   (
      query           => l_stmt,
      mv              => 'ACC_MGR_VIEW',
      statement_id  => 'MV_Explain_RW1'
   );
end;
/
commit
/
select message from rewrite_table
/

Результат показывает, что переписывание запроса не используется потому, что соединения, используемые в материализованном представлении и в запросе различны. В материализованном представлении соединяются четыре таблицы : ACCOUNTS, BALANCES, ACC_TYPES, и ACC_SUB_TYPES. А в запросе соединяются только три таблицы, SUB_ACC_TYPES не используется, о чем сообщается в столбце MESSAGE. Из-за отсутствия этого соединения, в случае использования переписывания запроса, можно получить неверный результат, поэтому оптимизатор решает не использовать его.

Если исправить запрос в Листинге 5 так, чтобы включить другой предикат AND SAT.ACC_SUB_TYPE = A.ACC_SUB_TYPE и поместить таблицу ACC_SUB_TYPE SAT в предложение FROM, то переписывание запроса должно стать возможным. Исправленный запрос приведен в Листинге 7. После того как администратор БД передаст исправленный запрос в процедуру, как показано в Листинге 6, проверка таблицы REWRITE_TABLE принесет хорошие новости:

SQL> SELECT MESSAGE 
         FROM REWRITE_TABLE;

QSM-01033: query rewritten with 
materialized view, ACC_MGR_VIEW

Код Листинга 7: Исправленный Листинг 5, чтобы сделать возможным переписывание запроса


SQL> set autotrace traceonly explain
SQL> select acc_type_desc,
  2           sum(cleared_bal)
  3   from balances b, 
  4          accounts a,
  5          acc_types at,
  6          sub_acc_types sat,
  7     where a.acc_no = b.acc_no
  8        and at.acc_type = a.acc_type
  9        and sat.sub_acc_type = a.sub_acc_type
 10   group by acc_type_desc

SQL> /

Execution Plan
--------------------------------------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=4 Bytes=64)
   1    0   SORT (GROUP BY) (Cost=6 Card=4 Bytes=64)
   2    1     MAT_VIEW REWRITE ACCESS (FULL) OF 'ACC_MGR_VIEW' (MAT_VIEW REWRITE) (Cost=5 Card=1600 Bytes=25600)

Запуск исправленного запроса, представленного в Листинге 7, подтверждает, что оптимизатор переписывает запрос и генерирует план выполнения, также включенный в Листинг 7. Этот план показывает, что вместо базовых таблиц используется материализованное представление ACC_MGR_VIEW, хотя пользователь указывал в запросе таблицы. Переписывание запроса действительно произошло.

Код Листинга 8: Сгенерированный скрипт для создания материализованного представления и его журналов


Rem  SQL Access Advisor: Version 10.1.0.1 - Production
Rem  
Rem  Username:        ARUP
Rem  Task:              MV_Tune_Task1
Rem  Execution date:   
Rem  

set feedback 1
set linesize 80
set trimspool on
set tab off
set pagesize 60

whenever sqlerror CONTINUE

CREATE MATERIALIZED VIEW LOG ON
    "ARUP"."ACCOUNTS"
    WITH ROWID, SEQUENCE("ACC_NO","ACC_TYPE","SUB_ACC_TYPE","ACC_MGR_ID")
    INCLUDING NEW VALUES;

ALTER MATERIALIZED VIEW LOG FORCE ON
    "ARUP"."ACCOUNTS"
    ADD ROWID, SEQUENCE("ACC_NO","ACC_TYPE","SUB_ACC_TYPE","ACC_MGR_ID")
    INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON
    "ARUP"."BALANCES"
    WITH ROWID, SEQUENCE("ACC_NO","CLEARED_BAL","UNCLEARED_BAL")
    INCLUDING NEW VALUES;

ALTER MATERIALIZED VIEW LOG FORCE ON
    "ARUP"."BALANCES"
    ADD ROWID, SEQUENCE("ACC_NO","CLEARED_BAL","UNCLEARED_BAL")
    INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON
    "ARUP"."ACC_TYPES"
    WITH ROWID, SEQUENCE("ACC_TYPE","ACC_TYPE_DESC")
    INCLUDING NEW VALUES;

ALTER MATERIALIZED VIEW LOG FORCE ON
    "ARUP"."ACC_TYPES"
    ADD ROWID, SEQUENCE("ACC_TYPE","ACC_TYPE_DESC")
    INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON
    "ARUP"."SUB_ACC_TYPES"
    WITH ROWID, SEQUENCE("SUB_ACC_TYPE","SUB_ACC_TYPE_DESC")
    INCLUDING NEW VALUES;

ALTER MATERIALIZED VIEW LOG FORCE ON
    "ARUP"."SUB_ACC_TYPES"
    ADD ROWID, SEQUENCE("SUB_ACC_TYPE","SUB_ACC_TYPE_DESC")
    INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW ARUP.ACC_MGR_VIEW
    REFRESH FAST WITH ROWID
    ENABLE QUERY REWRITE
    AS SELECT ARUP.SUB_ACC_TYPES.SUB_ACC_TYPE_DESC C1, ARUP.ACC_TYPES.ACC_TYPE_DESC
       C2, ARUP.ACCOUNTS.ACC_MGR_ID C3, ARUP.ACCOUNTS.SUB_ACC_TYPE C4, SUM("ARUP"."BALANCES"."CLEARED_BAL")
       M1, COUNT("ARUP"."BALANCES"."CLEARED_BAL") M2, SUM("ARUP"."BALANCES"."UNCLEARED_BAL")
       M3, COUNT("ARUP"."BALANCES"."UNCLEARED_BAL") M4, SUM(("ARUP"."BALANCES"."UNCLEARED_BAL"
       + "ARUP"."BALANCES"."CLEARED_BAL")) M5, COUNT(("ARUP"."BALANCES"."UNCLEARED_BAL"
       + "ARUP"."BALANCES"."CLEARED_BAL")) M6, COUNT(*) M7 FROM ARUP.SUB_ACC_TYPES,
       ARUP.ACC_TYPES, ARUP.BALANCES, ARUP.ACCOUNTS WHERE ARUP.ACCOUNTS.SUB_ACC_TYPE
       = ARUP.SUB_ACC_TYPES.SUB_ACC_TYPE AND ARUP.ACCOUNTS.ACC_TYPE = ARUP.ACC_TYPES.ACC_TYPE
       AND ARUP.ACCOUNTS.ACC_NO = ARUP.BALANCES.ACC_NO GROUP BY ARUP.SUB_ACC_TYPES.SUB_ACC_TYPE_DESC,
       ARUP.ACC_TYPES.ACC_TYPE_DESC, ARUP.ACCOUNTS.ACC_MGR_ID, ARUP.ACCOUNTS.SUB_ACC_TYPE;

whenever sqlerror EXIT SQL.SQLCODE

begin
  dbms_advisor.mark_recommendation('MV_Tune_Task1',1,'IMPLEMENTED');
end;
/

Как избежать уклоняющихся запросов

Как показано в Листинге 5, если пользователь пишет запросы немного по-другому, оптимизатор не переписывает запрос так, чтобы он выбирал из материализованного представления, и запрос выбирает непосредственно из базовых таблиц. Пользователь может считать, что запрос был переписан, и что результаты возвращаются из материализованного представления, но на самом деле, запрос не переписывается, и данные выбираются из исходных таблиц, что существенно увеличивает время отклика.

Следующие шаги

ПРОЧИТАЙТЕ больше о DBMS_MVIEW

Хинт REWRITE_OR_ERROR, включенный в SQL запрос, позволяет быть уверенным, что запрос переписывается так, чтобы выбирать данные из материализованного представления, или, если этого не произойдет, по крайней мере, сообщит пользователю об этом. Ниже показано добавление хинта REWRITE_OR_ERROR в SQL запрос (из Листинга 5), который не переписывается:

SELECT /*+ REWRITE_OR_ERROR */
       SELECT acc_type_desc, 
       sub_acc_type_desc,
...

Запрос вернет следующее сообщение об ошибке, если он не будет переписан:

ORA-30393: a query block in the statement did not rewrite
(ORA-30393: блок запроса в предложении не перезаписан)

Заключение

Oracle предоставляет инструменты для создания, управления и настройки материализованных представлений в пакете DBMS_MVIEW. Acme Bank существенно улучшил производительность запросов, применяя переписывание запросов, где это возможно, и используя сообщения об ошибках от запросов, которые не были переписаны, с тем, чтобы в дальнейшем оптимизировать эти запросы так, чтобы они использовали материализованные представления и переписывание запросов.


Аруп Нанда (arup@proligence.com) – менеджер систем баз данных в компании Starwood Hotels and Resorts в White Plains в Нью-Йорке. В 2003 году он получил от журнала Oracle Magazine звание Администратор БД Года, он также является соавтором книги “Oracle Privacy Security Auditing”, издательства Rampant Press (rampant-books.com), 2003.

E-mail this page