Обновление материализованного представления при изменении таблиц urderlying

У меня есть материализованное представление, определенное таким образом:

CREATE MATERIALIZED VIEW M_FOO
REFRESH COMPLETE ON COMMIT
AS
    SELECT FOO_ID, BAR
    FROM FOO
    WHERE BAR IS NOT NULL
    GROUP BY FOO_ID, BAR
/

COMMENT ON MATERIALIZED VIEW M_FOO IS 'Foo-Bar pairs';

Я написал как своего рода кеш: исходная таблица огромна, но количество разных пар довольно мало. Мне нужны эти пары, чтобы заставить их ПРИСОЕДИНИТЬСЯ с другими таблицами. Пока что так хорошо: он абсолютно ускоряет запросы.

Но я хочу убедиться, что представление не содержит устаревшие данные. Базовая таблица изменяется четыре или пять раз в месяц, но я не всегда знаю, когда. Я понимаю, что материализованное представление может быть определено так, чтобы оно обновлялось при изменении исходных таблиц. Однако документы становятся довольно сложными.

  • Какой точный синтаксис мне нужен использовать?

  • Нужно ли создавать материализованные просмотреть журнал?

  • Какая разница между быстрым и полное обновление?

Ответ 1

Чтобы ответить на ваши вопросы в обратном порядке

Быстрое обновление также называется инкрементным обновлением. Это должно дать вам ключ к разнице. Обновление COMPLETE восстанавливает весь MVIEW с нуля, тогда как обновление FAST применяет только изменения из DML, выполненные для таблиц фидеров.

Для выполнения обновлений FAST вам необходим соответствующий журнал MVIEW. Это отслеживает изменения в данных базовых таблиц, что позволяет Oracle эффективно применять delta к материализованному представлению, а не запрашивать всю таблицу.

Что касается синтаксиса, вот основы:

SQL> create materialized view log on emp
  2  with rowid, primary key, sequence (deptno, job)
  3  including new values
  4  /

Materialized view log created.

SQL> create materialized view emp_mv
  2  refresh fast on commit
  3  as
  4  select deptno, job from emp
  5  group by deptno, job
  6  /

Materialized view created.

SQL>

Предложение ON COMMIT означает, что MVIEW обновляется транзакционно (в отличие от ON DEMAND, который является регулярным массовым обновлением). В предложениях REFRESH указывается, применять ли инкрементные или полные обновления. Существуют некоторые категории запросов, которые заставляют использовать обновление COMPLETE, хотя, похоже, они уменьшаются с каждой новой версией Oracle.

Быстрый тест, чтобы увидеть, что это работает...

SQL> select * from emp_mv
  2  order by deptno, job
  3  /

    DEPTNO JOB
---------- ---------
        10 MANAGER
        10 PRESIDENT
        10 SALES
        20 ANALYST
        20 CLERK
        20 MANAGER
        30 CLERK
        30 MANAGER
        30 SALESMAN
        40 CLERK
        40 DOGSBODY

11 rows selected.

SQL>

Как насчет новой записи?

SQL> insert into emp (empno, ename, deptno, job)
  2  values (6666, 'GADGET', 40, 'INSPECTOR')
  3  /

1 row created.

SQL> commit
  2  /

Commit complete.

SQL> select * from emp_mv
  2  order by deptno, job
  3  /

    DEPTNO JOB
---------- ---------
        10 MANAGER
        10 PRESIDENT
        10 SALES
        20 ANALYST
        20 CLERK
        20 MANAGER
        30 CLERK
        30 MANAGER
        30 SALESMAN
        40 CLERK
        40 DOGSBODY
        40 INSPECTOR

12 rows selected.

SQL>

Более подробную информацию о синтаксисе можно найти в Справочнике по SQL. Также стоит прочитать главу Материализованное представление в Руководстве по хранилищу данных.


Несмотря на опасения комментаторов ниже, это работает как рекламируется. К сожалению, обычные места для публикации демонстраций (SQL Fiddle, db & lt;> fiddle) не допускают материализованных представлений. Я опубликовал что-то в Oracle SQL Live (требуется бесплатная учетная запись Oracle): я ожидаю одобрения Oracle и обновлю этот вопрос, когда он появится.

Ответ 2

Быстрое обновление будет только вставлять/обновлять/удалять измененные данные в материализованное представление. Полное обновление очистит материализованное представление, а затем скопирует все строки.

"on commit" означает, что материализованное представление будет обновляться всякий раз, когда изменение происходит в главной таблице. Таким образом, ваш текущий синтаксис будет крайне неэффективным. Каждый раз, когда кто-то меняет любую строку в foo, m_foo будет усечен, а затем каждая строка в таблице foo будет вставлена.

Вы можете сделать лучше с быстрыми обновлениями, где только измененные строки в foo будут отправлены в m_foo. Это дает вам последовательность без большого количества накладных расходов.

создать материализованный журнал просмотра на foo с помощью первичного ключа; - если у вас есть первичный ключ, вы должны создать материализованное представление m_foo быстро обновить фиксацию как \;

Есть несколько дополнительных тонкостей с грантами и синонимами, если вы используете ссылки db, или схема, которая владеет foo, не является той, которая владеет m_foo.