2011-11-21 30 views
5

Tengo una vista Materializada en Oracle que contiene una UNIÓN IZQUIERDA que lleva mucho tiempo actualizar. Cuando actualizo la tabla subyacente, se necesitan 63914.765 s para ejecutarse (sí, eso es casi 17 horas).Oracle - ACTUALIZACIÓN RÁPIDA Vistas materializadas con IZQUIERDAS se actualiza muy lento

Estoy utilizando un LEFT JOIN en la misma tabla, porque quiero pivotar los datos de las filas a las columnas. El comando pivote no está disponible en esta versión de Oracle, y no se permite el uso de GROUP BY + CASE en una vista materializada FAST REFRESH.

El materializada en Ver registro tiene el siguiente aspecto:

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

La misma vista materializada se parece a esto (que contiene 700.000 filas, la mesa Programmes_Titles contiene 900000 filas):

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' 

La instrucción UPDATE Yo uso es esto:

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

Esta declaración ACTUALIZADA ta kes 17 horas. Cuando se usa una UNIÓN INTERNA (eliminar las (+)) lleva milisegundos.

También traté de agregar ÍNDICES en la Vista Materializada de Mv_Web_Programmes, pero eso tampoco pareció ser de ayuda. (Todavía se ejecuta durante más de un minuto, que es una forma de ralentizar, no estoy esperando 17 horas después de cada cambio, por lo que podría mejorar la ACTUALIZACIÓN)

Así que mi pregunta es: ¿Por qué tarda tanto tiempo? ACTUALIZAR la tabla subyacente? ¿Cómo puedo mejorar esto?

Respuesta

3

He logrado reproducir su problema en una instancia 10.2.0.3. La autocomunicación y la combinación externa parece ser el problema principal (aunque con los índices en cada columna del MV, finalmente se actualizó en menos de un minuto).

Al principio pensé que podría utilizar un agregado 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 

Por desgracia, como habrán notado, a partir de 10 g a MV that contains MIN or MAX can only be fast-refreshed on commit after insert (los llamados única inserción MV). La solución anterior no funcionaría para la actualización/eliminación (el MV debería actualizarse manualmente).

Puede rastrear su sesión y abrir el archivo de rastreo para ver qué consulta SQL se ejecuta para que pueda encontrar si puede optimizarla a través de índices.

+0

Gracias, la solución sugerida funciona perfecto. Solo una pregunta adicional. En mi consulta de ejemplo, solo uso un único criterio en JOIN, pero mi consulta real usa dos. ¿Todavía puedo usar la función DECODE (esta es una nueva para mí o debería usar un CASE en su lugar?) – Tejo

+0

Disculpa, estaba siendo un poco rápido. La tabla Programme_Titles se actualiza con el nuevo valor en un segundo, pero Mv_Web_Programmes no se actualiza, el valor anterior aún está allí. ¿Alguna idea? – Tejo

+0

Debería poder usar CASE en lugar de DECODE, siempre que cada columna que use en su declaración CASE también esté en el registro MV. –

1

Nosotros también enfrentamos este problema recientemente en Oracle 11.2.0.3

En nuestro caso, era inevitable para eliminar un 'OUTER JOIN' debido al impacto funcional.

En la investigación, se encontró que Oracle estaba agregando una desagradable sugerencia HASH_SH (Hash Semi Join) con MV refresh DML.

Nada funcionó incluyendo cosas que se mencionan en los siguientes blog- http://www.adellera.it/blog/2010/03/11/fast-refresh-of-join-only-mvs-_mv_refresh_use_stats-and-locking-log-stats/#comment-2975

Al final, una pista oculta trabajó ... (aunque, en general, se debe evitar al hacer el cambio en la aplicación si es posible)

Oracle Doc ID 1949537.1 sugiere que establecer el parámetro oculto _mv_refresh_use_hash_sj en FALSE debe evitarlo con esa sugerencia.

alter session set "_mv_refresh_use_hash_sj"=FALSE; 

Que paró CBO con la sugerencia HASH_SJ.

Publicarlo aquí en beneficio de los demás.

Cuestiones relacionadas