Vistes materialitzades d'Oracle per optimitzar un Datawarehouse

Com les càrregues d'un Data warehouse es realitzen de manera periòdica, i a més és habitual la creació de taules agregades per millorar l'eficiència i temps de resposta dels nostres informes, un recurs d'optimització física que pot aportar grans millores és la utilització de vistes materialitzades.

La vista materialitzada no és més que una vista, definida amb una sentència SQL, de la qual a més d'emmagatzemar la seva definició, s'emmagatzemen les dades que retorna, realitzant una càrrega inicial i després cada cert temps un refresc dels mateixos.

Així, si tenim un Datawarehouse que s'actualitza diàriament, podríem utilitzar vistes materialitzades per anar actualitzant taules intermèdies que alimentin els nostres esquemes de DWH, o directament per implementar taules agregades que es refrescaran a partir de les nostres taules basi. 

La creació d'aquest tipus de vistes no tan complexa com pot semblar, el més important és tenir clar cada quant temps volem actualitzar la informació de les vistes, i quin mètode de refresc utilitzar.

 

Sintaxi bàsica per la creació d'una vista materialitzada

CREATE MATERIALIZED VIEW la meva_vista_materialitzada
             [TABLESPACE el meu_tablespace]
             [BUILD {IMMEDIATE | DEFERRED}]
             [REFRESH {ON COMMIT | ON DEMAND | [START WITH data_inici] NEXT data_interval } |
                            {COMPLETI | FAST | FORCE} ]
             [{ENABLE|DISABLE} QUERY REWRITE]
AS SELECT t1.camp1, t2.camp2
      FROM la meva_taula1 t1  , la meva_taula2 t2
      WHERE t1.camp_fk = t2.camp_pk
         AND …

Comentaris sobre les diferents opcions:

  • Càrrega de dades en la vista

BUILD IMMEDIATE:
Les dades de la vista es carreguen en el mateix moment de la creació

BUILD DEFERRED:
  Només es crea la definició, les dades es carregaran més avanci. Per realitzar aquesta càrrega es pot utilitzar la funció REFRESH del package DBMS_MVIEW:
    begin
         dbms_mview.refresh('la meva_vista_

materialitzada');
      end;
 

 

  • Mètode i temporalitat del refresc de les dades

    Cada quant temps es refrescaran:

    REFRESH ON COMMIT:
        Cada cop que es faci un commit en els objectes origin definits en la select

    REFRESH ON DEMAND:
      Com amb l'opció DEFERRED del BUILD, s'utilitzaran els procedures REFRESH, REFRESH_ALL_MVIEWS o REFRESH_DEPENDENT del package DBMS_MVIEW

REFRESH [START WITH data_inici] NEXT data_interval:
  START WITH indica la data del primer refresc (data_inici sol ser un SYSDATE)
  NEXT indica cada quant temps s'actualitzarà (data_interval podria ser SYSDATE +1 per realitzar el refresc una vegada al dia)

 

  • De quina manera es refrescaran

REFRESH COMPLETE:
El refresc es farà de totes les dades de la vista materialitzada, la recrearà completament cada cop que es llanci el refresc

REFRESH FAST:
El refresc serà incremental, és l'opció més recomanable, el de fast ya dóna una idea del perquè.
Aquest tipus de refresc té bastants restriccions segons el tipus de vista que s'estigui creant.
Es poden consultar en General Restrictions on Fast Refresh de la documentació oficial d'Oracle

Una de les coses importants a tenir en compte és que per poder utilitzar aquest mètode gairebé sempre és necessari haver creat abans un LOG de la Vista materialitzada, indicant els camps clau en els quals es basarà el manteniment de la vista.
S'utilitza la instrucció CREATE MATERIALIZED VIEW LOG ON:

   CCREATE MATERIALIZED VIEW LOG ON la meva_taula_origen
      WITH PRIMARY KEY
      INCLUDING NEW VALUES;
 

REFRESH FORCE:
Amb aquest mètode s'indica que si és possible s'utilitzi el metodo FAST, i si no el COMPLETI. 

Per saber si una vista materialitzada pot utilitzar el mètode FAST, el package DBMS_MVIEW proporciona el procedure EXPLAIN_MVIEW 

  • Activació de la reescritura de consultes

ENABLE QUERY REWRITE:
Es permet a la base de dades la reescritura de consultes

DISABLE QUERY REWRITE:
Es desactiva la reescritura de consultes

L'opció QUERY REWRITE és la que més anem a utilitzar si volem les vistes materialitzades per optimitzar nostre Data warehouse.
Aquesta opció permet crear taules agregades en forma de vistes materialitzades, i que quan es llanci una SELECT la base de dades pugui reescriure-la per consultar la taula o vista que vagi a retornar les dades sol·licitades en menys temps, tot de manera totalment transparent a l'usuari

L'únic que cal fer és crear les taules agregades com a vistes materialitzades amb QUERY REWRITE habilitat.

 

Exemples de vistes materialitzades

Són moltes combinacions, però la sentència final no és tan complexa.

 

Primer pas de l'ETL

Si volguéssim crear una vista materialitzada d'una taula que es refresqui un dia a la setmana, i de manera incremental faríem el següent: 

CREATE MATERIALIZED VIEW LOG ON la meva_taula_origen
   WITH  PRIMARY KEY
   INCLUDING NEW VALUES; 
CREATE MATERIALIZED VIEW la meva_vista_materialitzada
  REFRESH FAST  NEXT SYSDATE + 7
  AS SELECT camp1, camp2, camp8
        FROM la meva_taula_origen
    WHERE camp2 > 5000;

Aquesta vista podria servir-nos per alimentar la càrrega d'un Data Mart que es realitzés setmanalment. Podríem programar-la perquè es refresqués just abans de l'inici del procés de càrrega, o com a primer pas en l'ETL, i ja tindríem les dades necessàries actualitzades, i independents de l'origen de dades (no hauríem de molestar més a l'operacional). Un altre avantatge a tenir en compte és que si hi ha algun problema amb l'accés a les dades origen, si no els hem eliminat, en la vista materialitzada encara tindrem les dades de l'últim refresc, amb el que encara que el refresc fallés no ens trobaríem un error que trunqués la càrrega de nostre Data Warehouse, o una taula buida.
Per descomptat, en les condicions del WHERE podríem seleccionar només els registres necessaris, només els de l'últim mes, etc.

 

Taules agregades

Un altre exemple important seria la utilització de vistes materialitzades per la creació de taules agregades:

CREATE MATERIALIZED VIEW vendes_agregades_mv
  BUILD IMMEDIATE
  REFRESH COMPLETI
  ENABLE QUERY REWRITE
AS
  SELECT aneu_producte, sum(import) total_vendes
  FROM vendes;

 

Amb aquesta senzilla sentència es crearia una taula agregada de total de vendes per producte d'una suposada taula de vendes que seria la taula de fets.

A nivell de sessió també caldria assegurar-se que l'opció QUERY_REWRITE estigués activada. Per si per ventura s'habilita amb

ALTER SESSION SET QUERY_REWRITE_ENABLED=TRUE;

Si ara dintre d'aquesta sessió s'executa la sentència

SELECT sum(import)
FROM vendes;

la base de dades prepararà el pla d'execució tenint en compte la vista materialitzada creada i internament realitzarà la selecció sobre la vista vendes_agregades_mv.

Una manera senzilla de comprovar-ho, apart d'examinar el pla d'execució, o de comparar temps abans i després de la creació de la vista, o desactivant el QUERY_REWRITE, és comprovar que aquesta sentència retorna resultats en el mateix temps que la sentència

SELECT sum(import)
FROM vendes_agregades_mv;

 

Per consultar més detalls, o la sintaxi completa de la creació de vistes materialitzades en el capítol Create Materialized View del manual de referència SQL d'Oracle

 Amb enterprise manager o amb la consola web de la base de dades també es poden crear les vistes materialitzades d'una manera més assistida, però igualment és important tenir clars els conceptes abans de fer-ho.

Vistas materializadas en Oracle Enterprise Manager

Cerca amb el motor de Google

Google