Como leer el plan de ejecucion

Para comprender como se debe leer un plan de ejecucion comencemos con un ejemplo muy simple. Veamos a continuacion un plan de ejecucion sencillo:

Query Plan
--------------------------------------------------
SELECT STATEMENT     [CHOOSE] Cost=1234
  TABLE ACCESS FULL EMPLEADOS [:Q65001] [ANALYZED]

Cuando analizamos un plan de ejecucion, el paso que esta indentado mas a la derecha es la primer operacion que se realiza para la ejecucion de la sentencia (mas adelante veremos como se hace para determinar el orden de los pasos cuandoleemos un plan de ejecucion). Por lo tanto, en nuestro ejemplo, la primer operacion es TABLE ACCESS FULL EMPLEADOS. Este paso indica que estamos haciendo un barrido o recorrido completo de la tabla EMPLEADOS. Una vez finalizado dicho recorrido, el conjunto de filas resultante sera pasado al nivel superior para que siga procesando el query. Es decir que los datos seran pasados a la operacion SELECT que es la ultima etapa de la sentencia de nuestro ejemplo.

[CHOOSE] indica cual es el valor de optimizer_goal para el query. Esto no necesariamente indica que el plan haya utilizado dicho objetivo. La unica forma de confirmarlo es mirando la variable  COST= que tambien es parte del plan de ejecucion. En el ejemplo el costo tiene valores, indicando que se utilizo CBO (optimizador basado en costos).

SELECT STATEMENT     [CHOOSE] Cost=1234

Si el plan de ejecucion hubiera dicho

SELECT STATEMENT     [CHOOSE] Cost=

entonces el optimizador utilizado seria RBO (optimizador basado en reglas).

Es posts posteriores veremos en detalle que es el optimizador y que significa CBO o RBO. El objetivo de este articulo es aprender a leer un plan de ejecucion, no a interpretarlo. Aprender a interpretarlo es un poco mas complejo pues requiere de muchos otros conceptos previos. Obviamente, todos estos conceptos seran tratados oportunamente en SqlEficiente. El numero que acompaña al costo es un valor que utiliza Oracle internamente a fines comparativos para determinar cual es el plan que tiene el mejor costo. Los valores de los costos no sirven para comparar sentencias diferentes.

[:Q65001] indica que esta operacion particular del query se ejecuta en paralelo. Es decir que sera ejecutada por procesos esclavos en paralelo en vez de ser ejecutada por un solo proceso en forma serializada.

[ANALYZED] indica que el objeto en cuestion (en nuestro caso, la tabla EMPLEADOS) ha sido analizado y hay estadisticas disponibles sobre dicho objeto para que las puede utilizar el optimizador basado en costos.

Para determinar el orden en que se ejecutan cada unos de los pasos del plan de ejecucion de la sentencia es necesario entender las siguientes relaciones PADRE-HIJO:

PADRE
  PRIMER HIJO
  SEGUNDO HIJO

En este ejemplo, la sentencia PRIMER HIJO se ejecuta primero, luego se ejecuta la sentecia SEGUNDO HIJO y por ultimo PADRE procesa la salida de ambos hijos.

Veamos a continuacion un caso mas complejo:

PADRE
  PRIMER HIJO
    PRIMER NIETO
  SEGUNDO HIJO

Aplicando los mismo principios, PRIMER NIETO es la primer operacion, en segundo lugar se ejecuta la operacion PRIMER HIJO seguida por SEGUNDO HIJO. Por ultimo, la operacion PADRE.

Estos mismos principios pueden utilizarse para aplicarlos a las operaciones reales de un plan de ejecucion. Veamos algunos ejemplos concretos.

Ejemplo 1

set autotrace traceonly explain
select ename,dname
  from empleados, deptos
 where empleados.deptno=deptos.deptno
   and dept.dname in ('TESORERIA','COMPRAS','VENTAS','OPERACIONES');
15 rows selected.

Este query produce el siguiente plan de ejecucion:

Execution Plan
---------------------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=8 Bytes=248)
   1    0   HASH JOIN (Cost=3 Card=8 Bytes=248)
   2    1     TABLE ACCESS (FULL) OF 'DEPTOS' (Cost=1 Card=3 Bytes=36)
   3    1     TABLE ACCESS (FULL) OF 'EMPLEADOS' (Cost=1 Card=16 Bytes=304)

En el plan de ejecucion vemos dos columnas de numeros que preceden al texto de cada fila. El primer numero es el identificador de sentencia (tambien llamado ID). El segundo numero es el identificador del padre (tambien llamado parent ID) de la operacion en cuestion. La primer operacion no tiene identificador de  padre ya que es la primera de todas. El ID y el PARENT ID son utilizados por el generador de planes del optimizador para construir el plan de ejecucion. Los pasos del plan de ejecucion son indentados para indicar la jerarquia y dependencia de las operaciones.

En nuestro ejemplo, el plan de ejecucion comienza con ID=0

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=8 Bytes=248)

ID=0 no tiene padre, pero tiene un hijo.
ID=0 es padre de ID=1. Ademas ID=0 depende de las filas que devuelva ID=1
Por lo tanto ID=1 debe ejecutarse si o si antes que ID=0

Pasemos a ID=1:

   1    0   HASH JOIN (Cost=3 Card=8 Bytes=248)

ID=1 es hijo de ID=0
ID=1 is padre de ID=2 y de ID=3 y depende de las filas que le devuelvan ambos hijos.
Por lo tanto ID=2 y ID=3 deben ejecutarse si o si antes que ID=1

Pasemos a ID=2:

   2    1     TABLE ACCESS (FULL) OF 'DEPTOS' (Cost=1 Card=3 Bytes=36)

ID=2 es el primer hijo de ID=1
ID=2 no tiene hijos.
Este es el primer paso en la ejecucion de este query.
Las filas retornadas por esta operacion seran provistas a ID=1.

ID=1 tambien depende de ID=3:

   3    1     TABLE ACCESS (FULL) OF 'EMPLEADOS' (Cost=1 Card=16 Bytes=304)

ID=3 es el segundo hijo de ID=1
ID=3 no tiene hijos.
Esta es la seguna operacion que se ejecuta en este query.
Las filas retornadas seran provistas a ID=1.

ID=1 procesa las filas quer recibe de las operaciones de las cuales depende (ID=2 y ID=3) y retorna las filas a su padre
ID=0.
ID=0 retorna las filas al usuario.

En resumen:

La ejecucion comienza con ID=0: SELECT STATEMENT que depende de sus hijos para resolver el query por lo tanto ejecuta a su primer hijo ID=1 PID=0 HASH JOIN que a su vez depende de otros objetos hijo y por lo tanto ejecuta a su primer hijo ID=2 PID=1   TABLE ACCESS (FULL) OF ‘DEPTOS’  y luego a su segundo hijo ID=3 PID=2   TABLE ACCESS (FULL) OF ‘EMPLEADOS’
Las filas van siendo retonadas a los padres hasta llegar al final.

Anuncios

4 comentarios

  1. muy útil, gracias!
    ahora ya se como leerlo, podría decirme como interpretarlo?!?1

    Gracias nuevamente!

  2. Sale algo así:

    cómo se interpretabien ??

    EXPLAIN PLAN FOR
    SELECT e.employee_id, j.job_title, e.salary, d.department_name
    FROM employees e, jobs j, departments d
    WHERE e.employee_id < 103
    AND e.job_id = j.job_id
    AND e.department_id = d.department_id;
    The resulting output table in Example 13-2 shows the execution plan chosen by the optimizer to execute the SQL statement in the example:
    Example 13-2 EXPLAIN PLAN Output
    ———————————————————————————–
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
    ———————————————————————————–
    | 0 | SELECT STATEMENT | | 3 | 189 | 10 (10)|
    | 1 | NESTED LOOPS | | 3 | 189 | 10 (10)|
    | 2 | NESTED LOOPS | | 3 | 141 | 7 (15)|
    |* 3 | TABLE ACCESS FULL | EMPLOYEES | 3 | 60 | 4 (25)|
    | 4 | TABLE ACCESS BY INDEX ROWID| JOBS | 19 | 513 | 2 (50)|
    |* 5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | | |
    | 6 | TABLE ACCESS BY INDEX ROWID | DEPARTMENTS | 27 | 432 | 2 (50)|
    |* 7 | INDEX UNIQUE SCAN | DEPT_ID_PK | 1 | | |
    ———————————————————————————–

    Predicate Information (identified by operation id):
    —————————————————
    3 – filter("E"."EMPLOYEE_ID"<103)
    5 – access("E"."JOB_ID"="J"."JOB_ID")
    7 – access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")

  3. como seria para generar el plan de ejecución pero desde java?

  4. como interpreto: select * from alumnos where fono in null


Comments RSS TrackBack Identifier URI

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s