Oracle - FAST REFRESH. Материализованные представления с LEFT JOINS обновляются очень медленно - PullRequest
5 голосов
/ 21 ноября 2011

У меня есть материализованное представление в Oracle, которое содержит LEFT JOIN, обновление которого занимает очень много времени.Когда я обновляю базовую таблицу, для ее запуска требуется 63914,765 с (да, это почти 17 часов).

Я использую LEFT JOIN для той же таблицы, потому что я хочу перенести данные из строк в столбцы.Команда pivot недоступна в этой версии Oracle, и использование GROUP BY + CASE недопустимо в материализованном представлении FAST REFRESH.

Журнал материализованного представления выглядит следующим образом:

CREATE MATERIALIZED VIEW LOG ON Programmes_Titles
WITH PRIMARY KEY, rowid
INCLUDING NEW Values;

Само материализованное представление выглядит следующим образом (оно содержит 700000 строк, таблица Programmes_Titles содержит 900000 строк):

CREATE MATERIALIZED VIEW Mv_Web_Programmes
REFRESH FAST ON COMMIT 
AS

SELECT
    t1.ProgrammeId,        
    t1.Title as MainTitle,
    t2.Title as SecondaryTitle,
    --Primary key
    t1.Title_Id as t1_titleId,
    t2.Title_Id as t2_titleId,

    t1.rowid as t1_rowid,
    t2.rowid as t2_rowid
FROM
    Programmes_Titles t1, 
    Programmes_Titles t2
WHERE
    t1.Titles_Group_Type = 'mainTitle'
    AND t1.Programme_Id = t2.Programme_Id(+) AND t2.Titles_Group_Type(+) = 'secondaryTitle'

Используемый мной оператор UPDATE:

UPDATE Programmes_Titles 
SET Title = 'New title' 
WHERE rowid = 'AAAL4cAAEAAAftTABB'

This UPDATEЗаявление занимает 17 часов.При использовании INNER JOIN (удаление (+)) это занимает миллисекунды.

Я также пытался добавить INDEXES в материализованное представление Mv_Web_Programmes, но, похоже, это тоже не помогло.(Это все еще длится более минуты, что очень медленно, я не жду 17 часов после каждого изменения, так что это может улучшить ОБНОВЛЕНИЕ)

Итак, мой вопрос: почему это такдолго обновлять базовую таблицу?Как я могу улучшить это?

Ответы [ 2 ]

3 голосов
/ 21 ноября 2011

Мне удалось воспроизвести вашу проблему на 10.2.0.3 экземпляре.Самостоятельное и внешнее объединение, по-видимому, является основной проблемой (хотя с индексами в каждом столбце MV оно, наконец, обновилось менее чем за минуту).

Сначала я подумал, что вы можете использовать агрегатный MV:

SQL> CREATE MATERIALIZED VIEW LOG ON Programmes_Titles
  2  WITH PRIMARY KEY, ROWID (programmeId, Titles_Group_Type, title)
  3  INCLUDING NEW Values;

Materialized view log created

SQL> CREATE MATERIALIZED VIEW Mv_Web_Programmes
  2  REFRESH FAST ON COMMIT
  3  AS
  4  SELECT ProgrammeId,
  5         MAX(decode(t1.Titles_Group_Type, 'mainTitle', t1.Title)) MainTl,
  6         MAX(decode(t1.Titles_Group_Type, 'secondaryTitle', t1.Title)) SecTl
  7    FROM Programmes_Titles t1
  8   GROUP BY ProgrammeId;

Materialized view created

К сожалению, как вы заметили, по состоянию на 10g MV, содержащее MIN или MAX, может быть быстро обновлено только при коммите после вставки (так называемый MV только для вставки),Вышеупомянутое решение не будет работать для обновления / удаления (MV должен был бы обновляться вручную).

Вы могли бы проследить ваш сеанс и открыть файл трассировки, чтобы увидеть, какой запрос SQL выполняется, чтобы вы могли найти, еслиВы можете оптимизировать его с помощью индексов.

2 голосов
/ 07 апреля 2015

Мы также недавно столкнулись с этой проблемой в Oracle 11.2.0.3

В нашем случае было неизбежно удалить 'OUTER JOIN' из-за функционального воздействия.

При расследовании этобыло обнаружено, что Oracle добавляет неприятную подсказку HASH_SH (Hash Semi Join) с обновлением MV DML.

Ничего не работает, включая вещи, упомянутые в следующем блоге - http://www.adellera.it/blog/2010/03/11/fast-refresh-of-join-only-mvs-_mv_refresh_use_stats-and-locking-log-stats/#comment-2975

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

Oracle Doc ID 1949537.1 предполагает, что установка скрытого параметра _mv_refresh_use_hash_sj в значение FALSE должна препятствовать его использованию в этой подсказке.

alter session set "_mv_refresh_use_hash_sj"=FALSE;

Это остановило CBO, используя подсказку HASH_SJ.

Размещение его здесь в интересах других.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...