Diferencias entre una Vista y una Vista Materializada en Oracle

Una Vista (View) es un objeto de Oracle que al consultarlo ejecuta por detrás una query y nos devuelve el resultado (donde la query puede acceder a una o varias tablas, otras vistas, utilizar funciones, etc). Cada vez que consultamos la vista el motor de base de datos ejecuta por detrás la query y va a buscar los datos al origen. Las vistas no ocupan espacio físico, ya que no almacenan datos. No hay diferencias en rendimiento si ejecutamos la query directamente o lo hacemos a través de una vista, ya que el motor debe calcular igualmente el plan de ejecución e ir a por los datos. En los proyectos en los que he participado normalmente usamos vistas cuando necesitamos recuperar los datos actualizados a través de queries complejas (joins entre varias tablas y/o vistas) o calcular KPIs. A diferencia de los procedimientos almacenados (stored procedures), que se ejecutan a demanda y persisten los datos en tablas, por lo que para procesos batch cumplen su función, pero no cuando necesitamos recuperar la foto actualizada del momento.

Por contra, una Vista Materializada (Materialized View) es otro tipo de objeto de Oracle que aunque técnicamente es lo mismo que una Vista (ejecuta una consulta sql por detrás), lo que hace es almacenar físicamente en caché el resultado de ejecutar esa query en un determinado momento, de forma que cada vez que consultemos la Vista Materializada lo que vamos a recuperar es lo que había en el origen en el momento en el que se creó o se refrescó la VM. El uso principal de este tipo de objetos es para agilizar procedimientos en los que hay queries muy largas y complejas. Esas queries se dividen en varias secciones y se generan vistas materializadas que se generan al principio del código y se utilizan como fuente más adelante. En mi experiencia, siempre hemos usado tablas temporales en lugar de vistas materializadas porque ofrecen más ventajas: permiten manipular la estructura de datos; no se persisten en la caché, si no en la propia base de datos.

Vista materializada y vista convencional en Bases de Datos Oracle

A modo de resumen rápido:

VistaVista materializada
No se persisten datos, no ocupa espacio físicoSe persisten los datos en la BD, por lo que ocupa espacio físico
Mismo rendimiento que ejecutar query directamenteMejor rendimiento, los datos ya están cacheados
Cada vez que se ejecuta se obtiene una foto actualizadaLa foto de los datos es de cuando se generó o actualizó por última vez
Comparativa entre vista y vista materializada en SQL

La sintaxis para crear una Vista materializada es:

CREATE MATERIALIZED VIEW nueva_vista_materializada
	[TABLESPACE nuestro_tablespace]
	[BUILD {IMMEDIATE | DEFERRED}]
	[REFRESH {ON COMMIT | ON DEMAND | [START WITH fecha_inicial] NEXT intervalo_tiempo } |
	{COMPLETE | FAST | FORCE | NEVER} ]
	[{ENABLE|DISABLE} QUERY REWRITE]
AS SELECT tabla1.campo_a, tabla2.campo_b
	FROM tabla1 , tabla2
	WHERE tabla1.campo_a = tabla2.campo_a

Donde podemos especificar de qué forma queremos que se recuperen los datos: de forma inmediata o en otro momento:

  • BUILD IMMEDIATE: El resultado se almacena al ejecutar la query
  • BUILD DEFERRED: Sólo se crea la definición, el resultado se almacenará más adelante. Para ello podemos utilizar cuando queramos llenarla la función REFRESH del paquete de Oracle DBMS_MVIEW.

También podemos especificar cada cuánto tiempo o cuándo queremos que se actualicen los datos de la vista:

  • REFRESH ON COMMIT: los datos se actualizan cada vez que se haga COMMIT sobre los objetos fuente.
  • REFRESH ON DEMAND: sólo se actualizarán cuando se haga manualmente a través de las funciones REFRESH de Oracle (más adelante se explica cuáles son y cómo invocarlas).
  • REFRESH [START WITH fecha_inicial] NEXT intervalo_tiempo: con esta sentencia podemos establecer una actualización periódica de la vista. La fecha_inicial puede definirse como sysdate y el intervalo_tiempo cada cuanto tiempo queremos realizar la tarea (podemos incrementar numéricamente el sysdate)

Y especificar si permitimos a Oracle o no reescribir las queries cuando en una consulta se intente acceder a las tablas origen, de forma que por detrás el duende de Oracle ataque directamente a las vistas materializadas, cuyo acceso y recuperación de datos es más rápido, sin que el usuario necesite hacer nada. Esto sólo lo hará el Optimizador de Oracle si la consulta lo permite (que las tablas a las que va a buscar la información coinciden con las tablas origen de la vista materializada).

  • ENABLE QUERY REWRITE: Oracle puede reescribir las queries
  • DISABLE QUERY REWRITE: lo contrario

La ventaja de este tipo de objeto la encontramos cuando la query asociada es muy compleja, tiene numerosos joins y se utiliza con frecuencia, ya que nos permite mejorar el rendimiento de la SQL al tenerla almacenada en memoria y ejecutarse una sóla vez. Sin embargo, el principal hándicap es que nos vemos obligados a mantenerla actualizada de forma regular para no perder calidad en los datos. Para ello podemos definir en el script de creación de la Vista Materializada el tipo de actualización que tendrá al ejecutar los métodos propios de Oracle para refrescarla. Existen los siguientes tipos de actualización para una Vista materializada

  • FAST: Es la opción más recomendada por su rendimiento. Es una actualización incremental, es decir, sólo actualiza los registros que hayan cambiado. Para que esta opción funcione correctamente necesitamos generar estadísticas de la vista para que Oracle esté al tanto de los cambios. La forma de hacerlo es creando un log de la vista materializada sobre la PK de cada tabla origen.
CREATE MATERIALIZED VIEW LOG ON tabla_origen
WITH PRIMARY KEY
INCLUDING NEW VALUES;
  • COMPLETE: regenera por completo el resultado al borrar y volver a ejecutar de nuevo la query.
  • FORCE: Es el valor por defecto. En caso de que se pueda, se ejecutará el FAST; si no, el COMPLETE.
  • NEVER: nunca se refresca la vista.

Si modificamos el origen y queremos que éste se refleje en la Vista materializada, tenemos que invocar a una función del paquete DBMS_MVIEW de Oracle que se encarga de actualizar los datos. Tenemos dos a nuestra disposición:

  • DBMS_MVIEW.REFRESH: con este método pasamos por parámetro la Vista Materializada para que se actualice:
begin

	DBMS_MVIEW.REFRESH('TABLA_EMPLEADOS');

end;
  • DBMS_MVIEW.REFRESH_DEPENDENT: mientras que con este lo que le pasamos por parámetro son todas las tablas origen de las que depende la vista:
begin

	DBMS_MVIEW.REFRESH_DEPENDENT('TABLA_ORIGEN_1', 'TABLA_ORIGEN_2', 'TABLA_ORIGEN_3');

end;

13 comentarios

  1. Una pregunta, Si «los objetos fuente» no estan disponibles en cierto momento la vista materializada sigue funcionando?,gracias, saludos

  2. Hola Luis,

    Sí, la vista materializada hace una foto de las tablas de origen, pero no las necesita para recuperar de nuevo esta información. En cambio la VISTA sí que necesita que el origen siga existiendo.

    Un saludo

  3. Hola Marcos.
    entonces las vistas normales no ocupan espacio? no como las materializadas que esas si que conlleva espacio y datos. es asi?
    un saludo y gracias por tus aportes

  4. hola, muy buen blog.
    Vamos a ver si me hago entender jeje.
    Yo quiero crear una VM sobre un objeto que es un sinónimo creado con dblink a otra base de datos (por ejemplo informix).
    Se puede hacer?

    muchas gracias

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

What is 7 + 12 ?
Please leave these two fields as-is: