Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Contenido
TEMA 1 .......................................................................................................................................... 3
Módulo 1: Procesamiento y complejidad de sentencias SQL ................................................... 3
Fases en el procesamiento de una sentencia SQL ................................................................ 3
G1. Complejidad de sentencias SQL ...................................................................................... 3
Módulo 2: El optimizador .......................................................................................................... 4
¿Qué es el optimizador?........................................................................................................ 4
¿Qué optimizador usaré? ...................................................................................................... 4
Los histogramas..................................................................................................................... 5
Módulo 3: Plan de ejecución ..................................................................................................... 6
Plan de ejecución: Cómo consultarlo e interpretarlo ........................................................... 6
Tipos de Join ........................................................................................................................ 12
¿Qué join usar? ................................................................................................................... 14
Tema 2 ......................................................................................................................................... 16
Módulo 1: En el SELECT ........................................................................................................... 16
COUNT(*) frente a COUNT(1).............................................................................................. 16
Orden de los campos en la SELECT...................................................................................... 16
S1. Campos necesarios en la select ..................................................................................... 16
Tema 3 ......................................................................................................................................... 17
Módulo 1: En el FROM ............................................................................................................ 17
Número de tablas en el FROM ............................................................................................ 17
Orden de las tablas en el FROM .......................................................................................... 17
Sentencias distribuidas........................................................................................................ 17
Tema 4 ......................................................................................................................................... 19
Módulo 1: En el modelo de datos ........................................................................................... 19
Exceso de índices................................................................................................................. 19
Índices redundantes ............................................................................................................ 19
Indices y Foreign Keys ......................................................................................................... 19
Uso de índices compuestos ................................................................................................. 20
Índices efectivos .................................................................................................................. 20
Tipos de datos obsoletos..................................................................................................... 21
Mi índice no se usa .............................................................................................................. 21
Bloqueos en índices bitmap ................................................................................................ 23
Tema 5 ......................................................................................................................................... 24
Módulo 1: En el WHERE .......................................................................................................... 24
Uso de Bind Variables.......................................................................................................... 24
Grandes INLIST .................................................................................................................... 26
Operadores sobre campos indexados ................................................................................. 26
Comparadores sobre campos indexados ............................................................................ 27
Conversiones implícitas ....................................................................................................... 27
Having y Where ................................................................................................................... 28
ROWNUM ............................................................................................................................ 28
Antijoin ................................................................................................................................ 30
Tema 6 ......................................................................................................................................... 32
Módulo 1: Ordenaciones/Agrupaciones ................................................................................. 32
General sobre la ordenación ............................................................................................... 32
ORDER BY ............................................................................................................................ 32
DISTINCT y GROUP BY ......................................................................................................... 32
UNION ALL frente a UNION ................................................................................................. 32
Tema 7 ......................................................................................................................................... 33
Módulo 1: En el INSERT ........................................................................................................... 33
Especificar Campos en el INSERT ........................................................................................ 33
TEMA 1
Cada vez que se solicita a Oracle el ejecutar una sentencia SQL, internamente se realizan una serie de
acciones, agrupadas principalmente en 3 bloques: Análisis (parse), Ejecución, Recogida de datos (fetch).
No se considera adecuado el realizar sentencias SQL muy muy largas y complejas, ya que son más costosas
de mantener y de entender por el resto. Además, estas sentencias complejas suelen provocar planes de
ejecución inadecuados.
Se recomienda el descomponer estas sentencias en varias llamadas SQL, aunque provoquen algo más de
código en nuestras aplicaciones. A la larga se mantienen mejor y dan mejores tiempos de respuesta.
Módulo 2: El optimizador
¿Qué es el optimizador?
Cada vez que se ejecuta una sentencia contra la base de datos, entre otras cosas Oracle debe decidir cuál
es el plan de ejecución óptimo (saber cómo acceder a cada objeto, y en qué orden se realizan lo joins a las
distintas tablas implicadas)
El optimizador es el que se encarga de realizarlo. Actualmente existen dos tipos de optimizadores para
Oracle:
Por Reglas: Los criterios para decidir el plan se realizan en base a una serie de reglas fijas,
independientemente del volumen o distribución de datos (por ejemplo, la existencia de índices, y
tipos de índices). El optimizador por reglas dejo de ser mantenido desde la versión 8 de Oracle, y
dejará de estar soportado a partir de la versión 10.
Por costes: Oracle tiene en cuenta el volumen y distribución de datos conforme a estadísticas
recogidas anteriormente. Dependiendo del volumen decide los órdenes de join o el uso o no de
índices, por ejemplo.
Resulta claro que, para el optimizador por costes, resulta imprescindible basarse en estadísticas fiables,
con lo que deben actualizarse periódicamente.
De los dos optimizadores existentes (reglas y costes), se aconseja siempre utilizar el optimizador por costes.
(El optimizador por reglas dejo de ser mantenido desde la versión 8 de Oracle, y dejará de estar soportado
a partir de la versión 10).
Valores posibles:
RULE Por reglas.
Por costes, optimizando devolución de las primeras
filas.
FIRST_ROWS
A partir de Oracle 9i: FIRST_ROWS,
FIRST_ROWS_[1|10|100|1000]
ALL_ROWS Por costes, optimizando devolución de todas las filas.
Oracle elige, si hay estadísticas en los objetos, intenta
CHOOSE
por costes (ALL_ROWS)
La utilización de las siguientes características de Oracle, forzará a utilizar el optimizador por costes frente
a reglas:
Tabla con PARALLEL fijado Domain Indexes (Inter Media)
Particionamiento Parallel Create Table As Select
IOT (Index Organized Tables) Índices basados en función
Índices inversos Query Rewrite activado
Cualquier hint, distinto de RULE
Los histogramas
Los histogramas son unas estadísticas más completas, que en determinadas ocasiones deben ser utilizadas
para proporcionar más información al optimizador por costes.
Las estadísticas normales que se ejecutan con ANALYZE, presuponen una distribución uniforme de los
datos. Por ejemplo, en una tabla tenemos un campo llamado estado. El analyze obtendrá el número total
de registros de la tabla (por ejemplo 2.000.000) y el número de valores distintos que contiene el campo
estado (por ejemplo 2 valores: PENDIENTE y TERMINADO). De esta forma, con las estadísticas de Oracle,
cuando hagamos una select a esa tabla preguntando sólo por el campo estado, entenderá que en total
buscaremos 1.000.000 de registros (total de registros / # valores distintos).
Esta suposición de distribución uniforme que realiza Oracle puede causar muchos problemas, si no se
cumple la distribución uniforme. Si resulta que, en mi tabla, el 90% de los campos tienen el valor
"TERMINADO", sería bueno que Oracle lo supiera, y saber que cuando se pregunte por el estado
"PENDIENTE", me devolverán muchos menos registros.
De esta forma, para aquellos campos en que exista una importante desviación de la distribución uniforme
de datos, se aconseja la creación de los histogramas, que en definitiva se encargan de conocer la cantidad
de registros existentes, para los distintos valores de los campos.
Hay que tener en cuenta que los histogramas, también son estadísticas de Oracle, con lo que deben
actualizarse periódicamente. La creación de histogramas, ralentiza la creación de estadísticas, y deben
utilizarse con moderación, en los casos que realmente sea necesario (distribución no uniforme).
Módulo 3: Plan de ejecución
Para la optimización de sentencias SQL, es básico conocer el plan de acceso (plan de ejecución) que
Oracle utiliza en la ejecución de la sentencia.
Es necesario que en el usuario exista una tabla llamada PLAN_TABLE, donde se almacena el plan de
ejecución. Si no existe esa tabla en el usuario que está ejecutando la sentencia, y dado que la estructura de
la PLAN_TABLE varía entre distintas versiones de Oracle, solicita al equipo de Administración de Base de
Datos, que te genere la tabla en tu usuario.
Desde SQL*Plus, ejecuta por ejemplo:
Es necesario que en el usuario exista una tabla llamada PLAN_TABLE, donde se almacena el plan de
ejecución. Si no existe esa tabla en el usuario que está ejecutando la sentencia, y dado que la estructura de
la PLAN_TABLE varia entre distintas versiones de Oracle, solicita al equipo de Administración de Base de
Datos, que te generen la tabla en tu usuario.
Desde SQL*Plus, ejecuta por ejemplo:
Oracle permite registrar en un fichero de traza todas las sentencias que se ejecutan en una sesión, y a partir
de este fichero, utilizando tkprof, puedes consultar los planes de ejecución. A continuación te mostramos
un ejemplo. Para averiguar en qué directorio, para la base de datos que utilizas, se crean los ficheros de
traza, ponte en contacto con el equipo de Administración de Base de Datos.
Con la sentencia ALTER SESSION SET SQL_TRACE=, activamos o desactivamos el volcado en el fichero de
traza. Localizamos el fichero de traza que hemos generado (tec01_ora_6857.trc):
La lectura en el orden de ejecución de este árbol se realiza de abajo a arriba y de izquierda a derecha. Si
tienes dudas a la hora de interpretar los planes de ejecución puedes consultar al equipo de Administración
de Base de Datos.
Tipos de Join
Cuando en una sentencia SELECT, en la cláusula FROM indicamos más de una tabla, Oracle al obtener los
datos debe ir "juntando" los datos de cada tabla, en función de las condiciones del WHERE. A esta unión es
a lo que llamamos el join.
Oracle, independientemente del número de tablas en el FROM, siempre realiza los joins de dos en dos
tablas. aplicando los resultados de unir dos tablas, a la siguiente tabla, y así sucesivamente hasta pasar por
todas las tablas del FROM.
Actualmente existen tres tipos de join distintos:
1.- Nested Loop
Puede cambiarse el comportamiento del optimizador, para que le elija otro método de join, utilizando los
hints USE_NL, USE_MERGE, USE_HASH.
El optimizador escoge una tabla como directora o "outer". Por cada registro de la "outer", Oracle busca en
la "inner" todos los registros que enlazan con los registros del "outer". En el siguiente ejemplo la tabla dept
es la directora, y por cada registro que se encuentra en dept, se buscan coincidentes en emp.
Sort-Merge Join
Sólo se puede realizar un sort-merge join con equijoin (=). Oracle ordena las dos fuentes de datos (si nos
estan ya ordenadas) por las columnas del equijoin. Oracle une las dos fuentes de datos, por cada par de
filas, y devuelve las que coinciden los campos de join.
En el siguiente ejemplo, Oracle se recorre primero toda la tabla DEPT utilizando el índice PK_DEPT. Como
los datos ya vienen ordenados por el índice, no es necesario ordenar los datos de DEPT. A continuación, se
recorre toda la tabla EMP, y los ordena por el campo deptno (SORT por el campo del equijoin).
Una vez ordenados los dos grupos de datos, Oracle une uno con otro (MERGE JOIN).
Hash Join
Sólo se puede utilizarse con equijoin (=), y utilizando el optimizador por costes. Suponiendo dos grupos de
datos siguientes:
S={1,1,1,3,3,4,4,4,4,5,8,8,8,8,10}
B={0,0,1,1,1,1,2,2,2,2,2,2,3,8,9,9,9,10,10,11}
El proceso es el siguiente:
1.- Se selecciona la tabla de origen más pequeña (S), que se leera entera para formar una tabla hash. Si
esta tabla hash no cabe en memoria, se realiza por particiones o trozos (aplicando una función hash
interna de Oracle), que son almacenados en disco (fan-out). Además de crearse una tabla hash (con el
máximo número de particiones existentes y que caben en memoria), se crea un vector bitmap con los
valores existentes en el campo de join.
2.1.- Bit-Vector Filtering: Se comprueba si el valor del campo de join existe en el vector bitmap creado. Si
no está en ese vector, se desprecia esa fila directamente.
2.2.- Se aplica la función hash al campo de join de B, si esa partición hash está en memoria, se devuelve
directamente la fila unida.
2.3.- Si esa partición hash no está en memoria, se escribe en un segmento temporal en forma de
partición o trozo como se hizo con la tabla S. De esta forma, se obtendrán conjuntos de particiones, que
tienen los registros a unir.
3.- Comparación de particiones. A partir de ahora se irán cogiendo particiones dos a dos una de cada
origen de datos (S y B). Se crea en memoria la tabla Hash de la partición más pequeña y se compara en
memoria con la otra partición, devolviendo las filas que cumplen la join.
Se repite el paso 3 hasta que se hayan procesado todas las particiones creadas.
Si las filas a devolver por el join no son muchas (por debajo de 10.000 filas aprox.) :
Oracle tiende a utilizar "Nested Loop"
Si las filas a devolver por el join son muchas (por encima de 10.000 aprox.):
Se aconseja utilizar el "Hash Join". (Siempre y cuando se utilice el optimizador por costes. Si no fuera así,
no hay más remedio que utilizar el "sort-merge join").
El "sort-merge join" se desaconseja (para muchas filas), por los costes de ordenación, con lo que se prefiere
utilizar "hash join" con optimizador por costes.
En verdad, la elección que realiza Oracle es mucho más compleja, y no depende exclusivamente del número
de registros, teniendo en cuenta los costes de las operaciones de E/S, las áreas de memoria de ordenación
y hash, las estadísticas existentes, el modelo de datos, los índices de acceso, etc. Aquí únicamente se
expresan a grandes rasgos como puede decidirse un plan u otro, aunque es el optimizador quien tiene más
información para decidir el plan de join óptimo (y ni aun así no siempre consigue la mejor elección).
Tema 2
Módulo 1: En el SELECT
En versiones anteriores a la 8i, la utilización de count(*), count(1) o count(c1) podía tener distintos tiempos
de respuesta al utilizar o no índices.
A partir de Oracle 8, la utilización de count(*) o count(1) es indiferente ya que puede utilizar accesos por
índice (fast index scan), obteniéndose los mismos tiempos de respuesta.
El orden de los campos en la cláusula SELECT, no afecta en absoluto al rendimiento de nuestras sentencias.
Se aconseja evitar el uso de SELECT *, restringiendo la búsqueda de campos en la "select" a los campos que
realmente son necesarios. De esta forma se disminuye el volumen de información accedido y transportado
desde el servidor al cliente. También se facilita el acceso rápido a índices, frente al acceso a índice->tabla
(cuando exista un índice que lo permita).
En el caso de necesitar utilizar todos los campos de la tabla, el no utilizar el SELECT * también puede
beneficiar para dar mayor claridad al leer nuestro código SQL, y evitar errores en los cursores al asignar
valores a variables.
Tema 3
Módulo 1: En el FROM
El optimizador por COSTES, debe elegir el orden en que debe realizarse las join entre las tablas (siempre
los joins se realizan de dos en dos tablas). Esta elección se realiza durante el PARSE de la sentencia,
probando todas combinaciones posibles de join, eligiendo la de menor coste.
Sucede que cuando el número de tablas en el FROM (nº de joins) es muy alto, el optimizador decide no
probar todas las combinaciones posibles ya que tardaría mucho tiempo, probando únicamente algunas de
las combinaciones, con lo que hay mayor probabilidad de que no se elija el mejor plan de ejecución.
Cuando el total de tablas en el FROM es mayor de ocho, Oracle puede que ya no realice todas las
comprobaciones necesarias y se elijan planes no óptimos.
Se aconseja intentar evitar poner más de 8 tablas en el FROM, realizar la consulta en varias SELECTs
separadas. Si es completamente imposible, y como última medida, se podría utilizar el hint "ORDERED", y
ordenar las tablas en el FROM según el orden más adecuado para realizar las JOINs.
Para el optimizador por COSTES (que es el que debemos utilizar), el orden de las tablas en el FROM no afecta
a los planes de ejecución ni al rendimiento de la sentencia.
La única excepción es cuando se utiliza el hint "ORDERED".
Sentencias distribuidas
Oracle permite de forma transparente al usuario, realizar consultas sobre objetos que se encuentra en
bases de datos remotas. Sin embargo, la transparencia no se mantiene en los planes de ejecución, y en el
rendimiento, con lo que debe de tenerse especial cuidado con sentencias sobre bases de datos distribuidas.
1.- SQL Remota: Cuando todas las tablas en el FROM pertenecen a tablas remotas en una misma base de
datos, se envía tal cual la sentencia a la base de datos remota, y como si estuviera en local, se obtiene el
plan de ejecución y se ejecuta. Los datos resultantes deben viajar de la base de datos remota a la base de
datos local.
2.- SQL Distribuida: cuando en el FROM aparecen tablas locales y remotas, o remotas en varias bases de
datos. Oracle debe desmembrar la sentencia, para mandar ejecutar la parte que corresponda a cada base
de datos, y ejecutar también la parte local en la base de datos local.
La base de datos local "se convierte en la directora" (si no se especifica lo contrario con un Hint) con lo que
es la base de datos que recibe todos los datos, y se encarga de hacer las "joins", agrupaciones y
ordenaciones.
Los únicos hints que funcionan sobre tablas remotas son los hints de definición del orden de join, y el tipo
de join a realizar. Los hints de método de acceso, paralelismo, etc. no funcionan sobre las tablas remotas.
Tema 4
Exceso de índices
Los índices nos pueden permitir mejorar los tiempos de acceso a la información almacenada en las tablas.
Sin embargo, el exceso de índices empeora las operaciones de INSERT, UPDATE y DELETE sobre la tabla, ya
que además de almacenar la información en la tabla, debe actualizar el índice.
Este empeoramiento en los tiempos depende mucho de la degradación del índice, del volumen de datos,
de la cantidad y frecuencia de las modificaciones en la tabla, del tamaño de los campos a indexar, etc. Ni
aún así, recomendamos preocuparse de aquellas tablas que tienen más de seis índices, replanteandose si
es verdaderamente necesario.
Índices redundantes
Consideramos que un índice es redundante y debería eliminarse cuando ya existe otro índice que contiene
las mismas columnas a la izquierda. Los siguientes índices serían redundantes:
Si en la tabla "padre" se van a realizar operaciones de update o delete, debe definirse en la tabla "hija" un
índice por los mismos campos de la foreign key, por dos motivos:
1. Rendimiento, mejorando al hacer update o delete en la "padre" la búsqueda en la hija que asegure
que se puede hacer el update o delete.
2. Por bloqueos entre la tabla "padre" e "hija":
Operación
Sin índice en campos FK de la tabla Con índice en campos FK de
realizada
"hija" la tabla "hija"
sobre tabla
"padre" Bloqueos "tabla" hija Bloqueos "tabla" hija
Hasta versión Oracle 8i: Versiones 7, 8, 8i y 9i:
Toda la tabla, para evitar cambios Los registros afectados.
DELETE inconsistentes. No se puede hacer
UPDATE ningún insert, update o delete en la
tabla hija.
A partir de version Oracle 9i:
Solo se bloquean los registros
afectados por los cambio de la tabla
padre, no permitiendo cambiar los
Un índice compuesto es un índice que está formado por varios campos. Es importante recordar que para
que el índice compuesto se utilice deben aparecer en la WHERE al menos el primer campo del índice.
Por ejemplo, tengo un índice formado por los campos c1, c2 y c3.
c1, c2
c1
c2
c3
c2, c3
c1, c3
Excepciones:
1. Index Fast Full Scan: Cuando existe un índice que tiene todos los campos especificados en la
SELECT, con lo que en lugar de hacer un Full Table Scan, realiza un escaneo completo del índice
(Index Fast Full Scan).
2. Se solicita un ORDER BY y los campos pertenecen a un índice que además no permite nulo.
3. A partir de Oracle 9i, aparece la posibilidad de utilizar el índice a traves de un "INDEX SKIP SCAN",
que en algunos casos puede mejorar el rendimiento respecto a "FULL TABLE SCAN". En cualquier
caso, se considera poco efectivo el uso de "INDEX SKIP SCAN", siendo recomendable seguir
definiendo el orden adecuado en los campos del índice (Novedad Oracle 9i).
Índices efectivos
Los índices son importantes para agilizar las búsquedas de datos. Es importante intentar crear siempre
índices lo más efectivos posible, conforme a las siguientes normas:
Campo Selectividad
dni Muy
selectivo
Los siguientes tipos de datos son obsoletos para Oracle (actualizado para versión 9.0.2):
Para aquellos tipos de datos que todavía están soportados por compatibilidad, es muy importante su
migración a los nuevos tipos de datos, para asegurar el funcionamiento de nuestras aplicaciones en
versiones futuras de Oracle, y para poder utilizar las mejoras que aportan los nuevos tipos de datos.
Mi índice no se usa
4. ¿Los campos del índice se utilizan para la join? Si es así el uso del índice depende de:
- El tipo de JOIN que se realiza. (NESTED LOOP es la única que permite el uso de un índice).
- El orden en que se realizan las JOIN. En concreto el NESTED LOOP dependiendo de que
tabla sea la entrante y cual la saliente puede que se use o no el índice.
5. ¿Se está aplicando alguna función sobre el campo indexado? (Regla "W4. Comparadores e
índices")
Una función del tipo SUBSTR(campo1,1,2) provoca que el índice no se use, a no ser que se utilice
un índice basado en función (el índice se crea aplicando la función SUBSTR).
6. ¿Se está realizando alguna conversión implícita de tipos? (Regla "W5. Conversiones implícitas")
Las conversiones implícitas pueden inhabilitar los índices. No utilice conversiones implícitas.
7. Usa el índice, pero no el que yo quiero.
El uso de un índice frente a otro es elegido por el optimizador por costes en función "del coste"
menor que implica usar uno frente a otro. Es muy muy difícil que dos índices tengan el mismo
coste (mismo tamaño, mismo número de hojas, profundidad, bloques, etc.). En el caso de que
esto sucediera, el optimizador por costes los elige en orden alfabético. Siempre queda la
posibilidad de los Hints, para asegurar el uso del índice que deseemos. (Regla "H1.
Consideraciones sobre los Hints")
8. Mi índice no es bueno.
Puede ser que mi índice no sea muy bueno (poco restrictivo). (Regla "M5. Índices efectivos").
Puede ser que los datos no están uniformemente distribuidos, y al no tener histogramas el
optimizador saque conclusiones equivocadas. (Véase "Generales sobre SQL-> El optimizador-> Los
histogramas").
9. ¿Preguntas por valores nulos?
Los valores nulos no son almacenados en el índice (para índices compuestos si todos los valores
son nulos, no se almacenan en el índice). No se puede usar un índice al preguntarse por valores
nulos (Regla "W4. Comparadores sobre campos indexados.")
10. Se está utilizando una tabla remota.
La utilización de tablas remotas (querys distribuidas) tiene su complejidad para el optimizador.
Más adelante publicaremos las recomendaciones para querys distribuidas.
11. ¿Está utilizando Parallel Query?
Asegurese que no está utilizando Parallel Query, y si sus tablas tienen activadas algún grado de
paralelismo. La utilización de parallel query provoca tendencia a realizar "Full Table Scan en
paralelo" frente a acceso por índices.
12. ¿Está usando bind variables?
En algunas circunstancias el uso de bind variables provoca el no usar índices ya que el optimizador
no conoce el valor del dato utilizado. y realiza precálculos fijos que puede ser erróneos.
Bloqueos en índices bitmap
Los índices Bitmap son un tipo de índices especiales de Oracle, que pueden resultar más beneficiosos que
los B*Tree, cuando el número de valores distintos que puede tomar el campo es muy reducido.
Estos índices, para cada uno de los valores distintos, almacenarán internamente un 1 ó un 0 por registro,
en función de si ese registro tiene o no ese valor. Pueden llegar a ocupar mucho más espacio, pero pueden
ser bastante más rápidos.
Sin embargo, tienen una desventaja muy importante, para entornos en los que se realicen modificaciones
o inserciones de forma concurrente por varios usuarios.
Cualquier operación DML (Data Manipulation Language) como son insert, update o delete, provocará un
bloqueo exclusivo en "parte" del índice, lo que puede impedir operaciones de modificación sobre esa tabla,
siempre y cuando afecte a los campos que forman parte del índice bitmap.
Normalmente se suelen utilizar de forma muy beneficiosa en entornos de toma de decisión (data
warehouse) y muy poco en entornos transaccionales online (OLTP).
Tema 5
Módulo 1: En el WHERE
La ejecución de una sentencia SQL requiere de unos pasos previos de "compilación" (parse) en los que se
analiza su sintaxis, se comprueba la existencia de los objetos, se verifican los permisos, y se decide su plan
de ejecución.
Desde versión 7 de Oracle, se incluyó una cache de sentencias SQL, albergada dentro de la Shared Pool que
se encarga de almacenar todas las sentencias SQL más recientes que se han ejecutado en la base de datos.
El objeto de esta cache es mejorar los tiempos de respuesta a la hora de ejecutar una misma sentencia
SQL. Si esa sentencia se encuentra en la cache, puede evitarse realizar los pasos previos de chequeo y plan
de ejecución, pasando directamente a ejecutar la sentencia SQL a partir de la información almacenada en
la cache.
Hard Parse
Cuando una sentencia no se encuentra en la cache de la Shared Pool, debe realizar un "hard parse" o un
parse completo, que implica obtener memoria para esa sentencia, chequear la sintaxis, los objetos, los
tipos de datos, y obtener su plan de ejecución. Este proceso es un proceso complejo, que requiere un uso
importante de CPU.
Soft Parse
Si esa sentencia ya se encuentra en la Shared Pool, "y es compartible", Oracle solo debe realizar un "soft
parse", mucho menos costoso.
- Están escritas a nivel ASCII exactamente igual. (incluyendo letras, espacios en blanco. mayúsculas,
etc.)
- Los objetos referenciados en ambas sentencias son los mismos (mismo usuario).
- En caso de utilizarse bind variables, son del mismo tipo y tamaño para ambas sentencias.
- El optimizador fijado para las dos sesiones que ejecutan las dos sentencias, debe ser exactamente
el mismo (rule, first_rows, all_rows).
- La configuración del NLS (National Language Support) debe ser la misma, para las dos sesiones
que ejecutan las dos sentencias.
Cada vez que esta sentencia se ejecute, podrá ser compartida y aumenta la probabilidad de realizar "soft
parse", independientemente del valor que se le asigne a la variable ":bindA".
En esta sentencia se utilizan las bind variables: "vsurname1", "vsurname2" y "vname" de forma
correcta para identificar los valores de búsqueda por apellidos y nombre.
Las bind variables "flagsurname2" y "flagname" se utilizan para determinar si estamos buscando
o no por segundo apellido y por nombre. Si estos flags valen 0 quiere decir que no buscan por ese
campo, y gracias al OR impiden la búsqueda en el resto de condición (surname2, customer_name).
Si valen 1, si buscan por la condición siguiente al OR.
Estos flags consiguen en parte mejorar el rendimiento de estas sentencias, siempre y cuando en
estos flags no se utilicen con bind variables. Si buscamos por nombre del cliente, por ejemplo, la
sentencia debería ejecutarse de la siguiente forma:
- Consultas por rangos. En algunas consultas donde se pregunta por rangos (>, <, between), o
cuando se utiliza un LIKE por ejemplo, el uso de bind variables puede provocar planes peores. Esto
es debido a que el optimizador no conoce el valor exacto de la variable, y no puede calcular
"cuanto" de grande es el rango a consultar. El optimizador asume reglas estimadas fijas, y puede
provocar planes peores.
Como norma general se aconseja el uso de las bind variables por el importante impacto que tiene en el
rendimiento de la base de datos. En los casos de utilizar particionamiento, histogramas, o sentencias
"pseudo-dinámicas", utilizarlas en los campos no afectados por el particionamiento, histrograma o "flag"
respectivamente. Ante cualquier duda puedes consultar con el equipo de Administración de Base de Datos.
Grandes INLIST
Consideramos que grandes INLIST son cláusulas IN en las que se detallan una gran lista de valores. Es
aconsejable substituir los grandes INLIST por tablas de búsqueda (realizando una join con una tabla que
contiene valores a buscar).
Mala práctica en
Buena práctica en WHERE
WHERE
WHERE importe +
WHERE importe= anticipo - 5000
5000 = anticipo
WHERE
TRUNC(fecha) = WHERE fecha BETWEEN TRUNC(sysdate) AND TRUNC(sysdate)+ 0.99999
TRUNC(sysdate)
WHERE
account_name =
WHERE account_name LIKE NVL( :acc_name,'%')
NVL( :acc_name,
account_name)
Conversiones implícitas
Cuando en una cláusula WHERE no coincide el tipo de datos de la columna, con el tipo de datos del valor
por el que se pregunta, Oracle puede no generar error, y realizar internamente una conversión
(conversiones implícitas).
Estas conversiones implícitas suelen provocar en muchos casos la no utilización de los índices.
Se considera una mala práctica permitir a Oracle que realice la conversión implícita. Debemos intentar
que los tipos de campo de las variables y los campos coincidan, o realizar expresamente la conversión.
Por ejemplo, en la tabla DEPT tenemos un índice con el campo "descripción" (varchar2). Esto es lo que
sucede:
Condición ¿Usa el índice?
WHERE descripción = 1
Having y Where
ROWNUM
La cláusula ROWNUM en un WHERE, se utiliza para devolver únicamente un número de registros del total
de registros que cumplen el resto de la condición WHERE.
La cláusula ROWNUM únicamente se puede utilizar con el operador "<" o "<=".
Respecto al uso conveniente o no de ROWNUM, en nuestra opinión se debe utilizar ya que es la única
manera que tenemos de "cortar" la devolución de registros a un total dado, pero debemos tener muy claro
que es lo que realmente sucede internamente en Oracle, ya que aunque se utilice el ROWNUM, Oracle puede
ser que utilice muchos más registros.
Primer ejemplo
Veamos el siguiente ejemplo, en este caso el optimizador consigue arrastrar el número de registros del
ROWNUM en casi todo el plan de ejecución, con lo que no parece que sea muy perjudicial.
1. Oracle realiza "TABLE ACCESS FULL" a toda la tabla VUELOS, recorriéndose en total 57.711
registros (no limitado por ROWNUM). A continuación se recorre a través de la primary key de la
tabla PLAZAS, llamada PLA_PK, pero en este caso si limita al número de registros de ROWNUM (9).
Se realiza un Hash Join, de estos dos bloques de datos, devolviéndo en total 9 registros.
2. Se realiza un "TABLE ACCESS FULL" de toda la tabla COMPANIAS, sin limitarse por ROWNUM,
encontrándose en total 8 registros. A continuación se realiza un Hash Join, de los 8 registros de
COMPANIAS y los 9 registros devueltos en el paso 1. El hash join devuelve 9 registros.
3. Se realiza el "COUNT STOPKEY" que es realmente contar hasta los 9 registros que se deben
devolver para respetar el ROWNUM<10 que aparece en la cláusula WHERE. En verdad este COUNT
en esta ejecución no filtra, ya que en el paso anterior ya se devolvían únicamente los 9 registros
deseados.
Tal y como se observa en este plan, las operaciones de "FULL TABLE SCAN" no se han limitado por el
ROWNUM, mientras que la operación "INDEX (FAST FULL SCAN)" sí que ha limitado los registros analizados,
y devolviendo 9 registros, ya ha conseguido devolver lo solicitado en el ROWNUM.
Segundo ejemplo
Veamos la misma sentencia, pero en este caso hemos puesto un par de Hints, para conseguir un plan de
ejecución mucho peor, pero que si nos permite mostrar cómo no se limita en todo el plan, por la condición
ROWNUM.
Este es su plan de ejecución con su estimación de coste y de registros:
En este plan de ejecución se observa que para devolver los nueve registros solicitados por ROWNUM<10,
se han recorrido en total (en diversas tablas) un total de 3.313.493 registros.
Antijoin
General Anti-Join
Un antijoin es una consulta que devuelve registros de una tabla que no se corresponden con registros de
otra tabla. De alguna forma, es la operación contraria a un "join".
En Oracle existen las siguientes formas de realizar un Anti-Join:
Con NOT IN
Con NOT EXISTS
Con MINUS
Con OUTER-JOIN
Oracle realiza primero la subselect (SELECT deptno FROM emp), con lo que como no tiene ninguna cláusula
WHERE se recorre toda la tabla emp. A continuación se recorre la tabla dept, buscando los departamentos
que no tienen ningún empleado asociado.
Sin embargo, reconstruyendo la sentencia con NOT EXISTS, obtenemos el siguiente resultado:
Oracle ahora realiza un NESTED LOOP, con lo que por cada departamento (DEPT) realiza una búsqueda POR
íNDICE en la tabla empleados (EMP). Así hemos evitado realizar el FULL SCAN de emp, accediendo ahora
por el índice del campo de join.
Tener en cuenta que asumimos que el volumen de la tabla EMP es suficientemente grande como para que
merezca la pena usar un índice frente a un full scan de toda la tabla.
Tema 6
Módulo 1: Ordenaciones/Agrupaciones
Las ordenaciones son operaciones costosas para la base de datos, y pueden ser uno de los motivos
importantes por los que nuestras sentencias no sean tan rápidas como deseamos.
Como norma general deben evitarse siempre que no sean imprescindibles.
Las operaciones, que obligan a una ordenación son:
Creación de un índice
Utilización de las cláusulas de agrupación GROUP BY, DISTINCT
Utilización de la cláusula ORDER BY
Join utilizando SORT-MERGE
Utilización de los operadores de conjunto UNION, INTERSECT y MINUS
ORDER BY
Utilizar la claúsula ORDER BY únicamente cuando sea importante para nuestra aplicación el obtener los
datos ordenados. Es frecuente utilizar ORDER BY sin ser necesario la ordenación.
DISTINCT y GROUP BY
Utilizar la claúsula DISTINCT cuando estemos seguros que se pueden devolver registros duplicados y nos
interese eliminarlos. Muy frecuente utilizar distinct sin ser necesario, forzando a una ordenación.
Lo mismo sucede con la cláusula GROUP BY, utilizándalo sin funciones de agrupación de forma innecesaria.
Los operadores de conjunto UNION, agregan los resultados de varias SELECTs. UNION frente a UNION ALL
realiza una ordenación adicional para eliminar registros repetidos.
Utilizar UNION ALL frente a UNION cuando no nos importe el recibir registros repetidos, o estemos seguros
de no recibir ningún repetido.
Tema 7
Módulo 1: En el INSERT
Se considera una muy mala práctica, el realizar INSERT indicando directamente los valores (VALUES)
presuponiendo el orden de los campos en la tabla. Cambios en el modelo de datos (eliminar columnas, o
cambios de orden) pueden provocar que nuestros programas fallen, o lo que es peor, que no fallen y se
inserten valores en columnas equivocadas.
FIRST_ROWS
Especifica que se utilice el optimizador por costes, intentando conseguir el mejor tiempo de respuesta,
penalizando quizás el consumo de recursos.
El optimizador en modo FIRST_ROWS tiene mayor tendencia al uso de índices, aunque implique aumento
de accesos a disco. (no siempre aconsejable).
Formato
CHOOSE
Especifica que se utilice el optimizador por costes si alguna tabla posee estadísticas. Si no, se utilizará el
optimizador por reglas.
Formato
RULE
Especifica que se utilice el optimizador por reglas.
Formato
ROWID
Especifica que se realice un acceso a través del RowId
Formato
INDEX
Especifica que se utilice un índice determinado.
Formato
La diferencia entre RANK y DENSE_RANK es que con DENSE_RANK no se permiten "huecos" en los valores
de ranking, cuando se repiten los valores por los que se hace el ranking.