Skip to main content

Command Palette

Search for a command to run...

Automatic Indexing en Oracle Exadata desde 19c: qué es y cómo funciona

Guía práctica con caso de uso y scripts

Updated
11 min read
Automatic Indexing en Oracle Exadata desde 19c: qué es y cómo funciona

Introducción

Oracle Exadata permite, desde la versión 19c de base de datos, usar la opción Automatic Indexing en Oracle Enterprise Edition sin necesidad de adquirir licencias adicionales.

Automatic Indexing es una característica de los Engineered Systems (Exadata) y Oracle Cloud. Por tanto, si estamos al menos en esta versión y en Exadata, puede delegarse la gestión de la mayoría de índices al motor de base de datos, tanto en lo que se refiere a su creación y mantenimiento como en la eliminación automática de índices creados manualmente y que no estén en uso.

Arquitectura

La base del Automatic Indexing está en el SQL Performance Analyzer y el Automatic SQL Tuning Set (ASTS).

Cuando está activado el Automatic Indexing, cada 15 minutos se levanta la tarea SYS_AUTO_INDEX_TASK y realiza 5 pasos:

  • Paso 1: Identificación y Captura.

    De los datos capturados por el ASTS de sentencias y su carga sobre columnas en tablas con estadísticas válidas no obsoletas, se identifican los índices candidatos.

  • Paso 2: Creación.

    Se crean los índices en estado INVISIBLE y UNUSABLE, esto es se crean en el diccionario pero no tienen segmentos asociados, así no hay coste de mantenimiento. Solo se crearán índices B-tree. En tablas particionadas, solo índices locales. Pueden ser tanto de una sola columna o multi-columna. Los índices suelen tener el prefijo SYS_AI, para ser fácilmente identificables.

  • Paso 3: Validación.

    Se valida la carga de trabajo por el SQL Performance Analyzer. En esta fase el índice se construye temporalmente y el SPA simula la carga, comparando el rendimiento usando el índice con el rendimiento obtenido con la opción de no usarlo. El índice permanece VALID pero INVISIBLE para el resto de usuarios.

  • Paso 4: Toma de decisión.

    Si el uso del índice conlleva una mejora de rendimiento, el índice se publica, se hace VISIBLEy USABLE, quedando disponible para el optimizador. Si se detectan consultas individuales que sufren regresión, se crea un SQL Plan Baseline para prevenir la regresión.

  • Si el rendimiento empeora o no mejora, el ínidice vuelve a marcarse como UNUSABLEy se purgará en el paso 5.

  • Paso 5: Purgado.

    Se limpian los índices que se descartaron en el paso 3 o los índices que se hicieron visibles si no son usados por un periodo de tiempo (por defecto 373 días). También puede configurarse para que se borren los índices creados manualmente no usados, aunque el comportamiento por defecto es no borrar los índices creados manualmente.

Restricciones

  • Es necesario que los binarios de oracle hayan sido compilados sin excluir explícitamente la opción Real Application Testing, esta es la configuración por defecto. No es necesaria la licencia RAT de forma independiente

  • Es necesario estar enOCIo enEngineered Systems Exadata.

  • En Exadata, hay que tener en cuenta que para que la creación del índice sea efectiva, no deben hacerse escaneos masivos, sino que deben extraerse pocas filas, escaneos masivos llevarán al uso del Exadata Smart Scan que es más rápido que el acceso por índice y por tanto el SPA no seleccionará el índice como opción de mejor rendimiento, eso deja fuera índices sobre tablas muy pequeñas.

  • Estadísticas actualizadas. Tablas sin estadísticas o con estadísticas obsoletas no serán tenidas en cuenta para el Automatic Indexing.

  • Indices Bitmap no serán candidatos a ser creados por Autmatic Indexing.

  • Indices globales en tablas particionadas tampoco.

  • Ni lo serán Índices de función, índices de clave inversa (Reverse Key Indexes).

  • Están excluidos los índices en tablas temporales y en tablas del sistema o propiedad de esquemas como SYS,SYSTEM,AUDSYS o del diccionario de datos.

  • No se crearán índices en columnas con tipo de dtaos no soportados, del tipo LOBs,LONG,SDO_GEOMETRY o tipos de datos definidos por el usuario.

Implementación de la prueba

En un entorno aisliado de test, limitaremos la prueba al esquema deSCOTTy a su tablespace por defectoUSERS.

Los valores iniciales son los de por defecto:

La configuración se hace mediante el paquete DBMS_AUTO_INDEX.

  • Habilitar el modo de implementación. Hay tres modos posibles, OFF,REPORT ONLYeIMPLEMENT. En nuestra prueba, se pondrá en IMPLEMENTque creará y hará visibles los índices:
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_MODE','IMPLEMENT');
  • Restricción al esquemaSCOTT. Pueden gestionarse listas de inclusión y exclusión, así como el uso de máscaras, para la prueba de concepto solo añadiremos a SCOTT a la lista de inclusión:
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_SCHEMA', 'SCOTT', allow => TRUE); 
  • Retención a 30 días de los índices no usados, al ser un entorno de pruebas vamos a reducir el valor por defecto de 373 días:
EXEC DBMS_AUTO_INDEX.CONFIGURE('AUTO_INDEX_RETENTION_FOR_AUTO', 30); 
  • Nos aseguramos que el esquema SCOTT tiene estadísticas:
EXEC DBMS_STATS.GATHER_SCHEMA_STATS(ownname => 'SCOTT', cascade => TRUE);

No se generarán índices automáticos sobre tablas que no tengan estadísticas actualizadas.

Modificamos la tabla emp para que las consultas sobre dicha tabla sean más óptimas por los índices que puedan crearse, lo hacemos quitando la Primary Key, cargando varios miles de registros y recalculando las estadísticas:

ALTER TABLE scott.emp DROP PRIMARY KEY CASCADE;
ALTER TABLE scott.emp MODIFY (empno NUMBER(10));

INSERT /*+ APPEND */ INTO scott.emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
SELECT 
    ROWNUM + 10000, 
    e.ename, 
    e.job, 
    e.mgr, 
    e.hiredate, 
    e.sal, 
    e.comm, 
    e.deptno 
FROM 
    scott.emp e
CROSS JOIN 
    (SELECT 1 FROM DUAL CONNECT BY LEVEL <= 100000);

COMMIT;


EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'EMP', cascade => TRUE);

Para simular actividad, generamos un job que no pare de hacer consultas a la tabla SCOTT.EMP por empno:



BEGIN
  DBMS_SCHEDULER.CREATE_JOB (
    job_name        => 'SCOTT.POC_AUTO_INDEX_WORKLOAD',
    job_type        => 'PLSQL_BLOCK',
    job_action      => '
      DECLARE
        v_ename VARCHAR2(50);
      BEGIN
        FOR i IN 1..5000 LOOP
          BEGIN 
            -- Buscamos por EMPNO. Selectividad del 100% (1 sola fila).
            -- El valor de :1 iterara desde 10001 en adelante.
            EXECUTE IMMEDIATE ''SELECT ename FROM scott.emp WHERE empno = :1'' 
            INTO v_ename USING (i + 10000);
          EXCEPTION 
            WHEN NO_DATA_FOUND THEN NULL;
            WHEN TOO_MANY_ROWS THEN NULL;
          END;
        END LOOP;
      END;',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'FREQ=MINUTELY; INTERVAL=2',
    enabled         => TRUE
  );
END;
/

También se forzaron jobs similares que repetían consultas sobre otros campos de la tabla emp sin indexar.

¿Como ver los resultados del proceso de Automatic Indexing?

El proceso de automatic indexing se ejecuta cada 15 minutos, y podemos identificarlo como una tarea SYS_AUTO_INDEX_TASK dentro de la vista dba_advisor_executions.

SELECT 
    task_name,
    execution_name,
    TO_CHAR(execution_start, 'YYYY-MM-DD HH24:MI:SS') AS execution_start,
    TO_CHAR(execution_end, 'YYYY-MM-DD HH24:MI:SS') AS execution_end,
    status
FROM 
    dba_advisor_executions
WHERE 
    task_name = 'SYS_AUTO_INDEX_TASK'
ORDER BY 
    execution_start DESC
FETCH FIRST 20 ROWS ONLY;

También puede verse ver el último report con el paquete DBMS_AUTO_INDEX y en función de su tiempo, podrá calcularse la siguiente ejecución:

DECLARE
  report CLOB := NULL;
BEGIN

  report := DBMS_AUTO_INDEX.REPORT_LAST_ACTIVITY(
    type    => 'TEXT',
    section => 'SUMMARY +INDEX_DETAILS +ERRORS',
    level   => 'BASIC'
  );
  DBMS_OUTPUT.PUT_LINE(report);
END;
/

La salida será:

Pasados al menos 15 minutos para que se ejecute el Automatic Indexing, debe haberse creado un índice INVISIBLE sobre el campo empno.

Para ver las ejecuciones en un rango de tiempo: (en github he subido chk_auto_indexing_report.sql)

Y el índice que ha creado tendrá la columna AUTO=YES en la DBA_INDEXES:

SELECT 
    o.owner,
    i.index_name, 
    i.table_name, 
    i.index_type,
    i.visibility,
    c.column_name,
    c.column_position,
    TO_CHAR(i.last_analyzed, 'YYYY-MM-DD HH24:MI:SS') AS last_analyzed,
    TO_CHAR(o.created, 'YYYY-MM-DD HH24:MI:SS') AS created,
    TO_CHAR(o.last_ddl_time, 'YYYY-MM-DD HH24:MI:SS') AS last_ddl_time
FROM 
    dba_indexes i,
    dba_objects o,
    dba_ind_columns c
WHERE 
    i.index_name = o.object_name
    AND i.owner = o.owner
    AND o.object_type = 'INDEX'
    AND i.index_name = c.index_name
    AND i.owner = c.index_owner
    AND i.table_name = c.table_name
    AND i.auto = 'YES'
ORDER BY 
    i.table_name ASC,
    i.index_name ASC, 
    c.column_position ASC;

Horas después, podemos verificar que ya hay mas índices creados automáticamente y el que se usa por el optimizador está en estado VISIBLE, esto indica que ha pasado la fase de validación indicada en el apartado de aquitectura.

Comparando planes de ejecución en awr, ver Comparar planes de ejecución en el AWR, he obtenido el plan antiguo y nuevo para la consulta a la tabla scott.emp filtrando por empno.

Y el nuevo plan con el índice:

Para borrar un índice creado con este método, no se puede aplicar el tradicional drop index, se borra automáticamente cuando el índice lleve sin usarse el tiempo configurado en el parametro AUTO_INDEX_RETENTION_FOR_AUTO, pero puede forzarse un borrado con la api, como ejemplo borraremos un índice de los creados pero todavia invisibles:

exec dbms_auto_index.drop_auto_indexes('SCOTT','"SYS_AI_1qg24s2ykdat4"',TRUE);

Con la opción TRUE, permitimos que vuelva a crearse automáticamente en un futuro.

Verificamos que ya no existe:

Si intento borrar un índice creado automáticamente de manera tradicional:

Si está permitido hacerle un rebuild o un coalesce, con lo que se puede cambiar de tablespace o sus parámetros de almacenamiento.

Pueden verse las últimas acciones ejecutadas por el Automatic Indexing con las vistas DBA_AUTO_INDEX_IND_ACTIONS y DBA_AUTO_INDEX_SQL_ACTIONS:

Licencias y versiones

Los únicos requisitos es estar en Exadata con Oracle Enterprise Edition 19c. Aunque el Automatic Indexing se basa en el Automatic SQL Tuning Set y en SQL Performance Analyzer, no es necesaria la licencia de Tuning & Diagnostic Pack.

https://docs.oracle.com/en/database/oracle/oracle-database/19/dblic/Licensing-Information.html#GUID-0F9EB85D-4610-4EDF-89C2-4916A0E7AC87

Según las notas leídas en MOS, deberíamos estar mínimo en oracle 19c RU 19.7 (KB119960).

Resumen

Son muy pocos los requisitos que debe cumplir una base de datos 19c Enterprise Edition en exadata para beneficiarse del Automatic Indexing, con una compilación por defecto, solo es necesario que las tablas candidatas tengan las estadísticas recientes y ya puede configurarse esta funcionalidad.

El mantenimiento automático de índices puede ser una gran ventaja al liberar al DBA o al administrador de la aplicación de la pesada tarea de mantener índices obsoletos o proponer la creación de índices nuevos.

El riesgo de regresión por causa de los nuevos índices no existe ya que el SPA valida el impacto de cada índice antes de liberarlo, creando SQL Plan Baselines para consultas que sufireron regresiones.

Una vez activado el Automatic Indexing, la automatización del proceso es completa. Todo se realiza en segundo plano sin requerir intervención del dba.

Aplicabilidad

Antes de decidir el uso en producción de esta potente funcionalidad, puede probarse en un entorno de test controlado bajo simulaciones de carga reales. Sin usar RAT para capturar y reproducir el tráfico de producción puede forzarse esa carga con herramientas tipo JMeter o LoadRunner o scripts a medida. El Automatic Indexing creará los índices que considere necesarios, en modo IMPLEMENT, o los mostrará solo en modo INVISIBLE y NO DISPONIBLE si se ha configurado en modo REPORT ONLY.

Un caso particular que puede ser solventado con esta funcionalidad, es el problema que se genera cuando aparecen foreign keys in indexar en entornos OLTPS.

Scripts usados

Notas y bibliografia

  • Oracle 19c Database Administrator’s Guide

  • El Automatic SQL Tuning Set (ASTS) captura de forma continua y sin intervención la carga de trabajo y almacena en el tablespace SYSAUX, las sentencias SQL, sus métricas de rendimiento, contextos y planes de ejecución. Es la base para la Indexación Automática y el Automatic SQL Plan Management.

KB119960 MOS Note: "Automatic SQL Tuning Sets (ASTS) 19c RU 19.7 Onwards" (Doc ID 2686869.1).

  • El SQL Performance Analyzer (SPA) es el componente del Real Application Testing (RAT) que evalua el impacto de los cambios del sistema en el rendimiento de las consultas antes de ser aplicadas en producción

    Oracle Database Testing Guide 19

    KB149029 SQL Performance Analyzer Summary

  • MOS Note: "SQL Performance Analyzer (SPA) White Paper and Links" (Doc ID 2102143.1)

    Licencias

Consideraciones

  • Las consultas que aparecen en el artículo se han elaborado a partir de la documentación oficial de Oracle y se ofrecen como ejemplos y herramientas de apoyo al diagnóstico. Se facilitan para su uso y adaptación, pero su aplicación en entornos productivos debe validarse previamente por el responsable del sistema o un DBA; cualquier modificación que afecte a la producción es responsabilidad del usuario. Para casos críticos o dudas, consulte la documentación oficial de Oracle y/o Oracle Support (MOS). Si detecta errores o desea proponer mejoras, agradeceremos sus informes o contribuciones mediante issues o pull requests.

  • Los problemas son reales, los datos no.