jueves, 8 de mayo de 2008

Bind Peeking

Estoy seguro que muchos de nosotros hemos tenido algun problema de mayor o menor escala con Bind Peeking introducido en Oracle 9i, especialmente los que migramos hace años de 8i a 9i.

Lo que hace bind peeking es si se utiliza las variables bind el primer parsing de un cursor (sentencia SQL) la variable se sustituye por el valor real y con ese valor se genera el plan de ejecucion, esto esta bien si todas las consultas usan ese valor que se ha generado el plan. Por ejemplo cuando consultas contra una tabla (con 500000 resgirtos) de facturas y quieres consultar las pendientes (estado), que podria representar solamente el 1% de la tabla, lo ideal es que el optimizador utilice un indice sobre el campo de estado, imaginense el primer parsing de la query es una consulta que en vez de consultar por el estado pendiente va por el estado cobrado, el plan de ejecucion seria un Full Table Scan sin embargo el resto de la gente que van a consultar por el estado pendiente seran las victimas de ese plan, una consulta que tarda millisegundos podria llegar a tardar hasta 30 segundos. (siempre partiendo con la idea de que la tabla tiene histogramas sobre el campo estado) Lo que es peor es que la consulta depende de los dias funciona bien ó mal y genera inestabilidades.

El bind peeking introduce de alguna manera alternativas e inteligencia que no existia en las versiones anteriores sin embargo se ha comprobado en numerosos casos que son los causantes de los problemas de rendimiento. De hecho aplicaciones como SAP, Siebel recomiendan deshabilitar bind peeking. En Oracle E-Business Suite me ha dado algun problemillas tambien.

Se ha visto que un plan de ejecucion no es optimo para todo los valores posibles de bind por lo tanto es necesario algun tipo de mecanismo mas inteligente que sea capaz de generar un plan de ejecucion por cada tipo de bind. En Oracle 11g se ha introducido el concepto de cursores inteligentes (Adaptive Cursor Sharing) y esto ayudara a generar los posibles planes de ejecucion para los diferentes valores de bind. Con esto supongo que se pretende eliminar los problemas que hemos sufrido por el bind peeking. Pero habria que estudiarlo muy bien porque parece que necesita varios parsing de un cursor para llegar a un punto estable y tener todos los planes de ejecucion, y parece ser que es necesario Soft Parsing para que esto funcione (que pasaria con Packages de PL/SQL?).


2 comentarios:

Anónimo dijo...

Hola.
Tengo una duda que no consigo aclarar. Quería hacerla aquí puesto que veo que tienes muchos conocimientos sobre el tema.

¿El orden de las tablas en la clausula FROM afecta a la velocidad de la consulta? ¿Hay que colocar las tablas que retornan más filas en las primeras posiciones?

Y, a la hora de enlazar tablas, ¿es mejor el uso de la nomenclatura ANSI con inner join que la vieja nomenclatura de oracle (+)? He leido que con los INNER JOIN mejora la velocidad ya que no hace todo el producto cartesiano de las tablas de la clausula FROM para luego filtrar por las condiciones del WHERE, como si parece que hace si usamos (+). Parece ser que solo hace el producto cartesiano de los registros de las tablas que cumplan con las condiciones ON del JOIN

Todo esto, referido a Oracle.

Aunque no me contestes, gracias por el blog. He aprendido mucho con él. Aunque también me han entrado más dudas.

Anónimo dijo...

Soy el del comentario anterior. Mi duda surge, entre otras cosas, por esto que leí:

Al ser el primer paso el producto cartesiano de las tablas que se encuentran listadas en el FROM, dependiendo del número de columnas de cada tabla y la cantidad de registros en cada una de ellas, se genera un resultado que puede llevarle demasiado tiempo al motor de BD, y luego tiene que aplicar la condición existente en la cláusula WHERE para reducir el número de registros resultante del producto cartesiano. Si nosotros realizamos la composición directamente en el FROM evitamos utilizar la cláusula WHERE para dicho propósito haciendo mucho más eficiente la consulta, ya que al momento de realizar el producto cartesiano estamos diciéndole al motor qué registros queremos de ese producto.