To bind or not to bind: that is the question

Tenemos un programa que hace en GeneXus: 

for each  
    where ATT1=&Var1 .or. &Var1='TODOS'   //Los puntos en el or son para darle olor a viejo            where ATT2=&Var2 .or. &Var2='TODOS'         
Msg('Cuantos registros tiene esta tabla!!!' +  Clave)
endfor

Esto va a generar una sentencia mas o menos asi:

SELECT CLAVE, ATT1, ATT2 FROM TABLAGRANDE
WHERE
(ATT1=@AV6969VAR1 OR @Av6969Var1='TODOS') AND
(ATT2=@AV6968VAR2 OR @AV6968VAR2='TODOS')
ORDER BY CLAVE

En la base de datos, las sentencia tiene una parte fija, y las variables, cambian en cada corrida, de form que el DBMS puede reutilizar la navegación y no necesita recompilar la sentencia, cuando cambian los valores de la variable. Esto deja a los DBA contentos. 

Que inconvenientes trae esto?

Generalmente estas sentencias, aparecen en la lista de sentencias que consumen mucho, pues los OR hacen que se consuman mas recursos que los necesarios. 

Que opción tenemos para mejorar esto con Genexus?

Utilizando WHEN en el for each, podemos hacer que la sentencia que se ejecute se arme en forma dinámica, lográndose que solamente llegue al manejador de base de datos, los filtros necesarios. 
Rescribiendo (*)  el codigo  anterior:

for each  
   where ATT1=&Var1 WHEN NOT &Var1='TODOS'      
   where ATT2=&Var2 WHEN NOT &Var2='TODOS'         
Msg('Cuantos registros tiene esta tabla!!!' +  Clave)
endfor

Eso va a generar una sentencia SQL que se armará en forma dinámica :

Sentencia="SELECT CLAVE, ATT1, ATT2 FROM TABLAGRANDE WHERE"
if (@AV6969VAR1<>'TODOS')
...   Sentencia = Sentencia + " ATT1=" + AV6969VAR1  
endif
if (@AV6969VAR2<>'TODOS')
...   Sentencia = Sentencia + " ATT2= " + AV6969VAR2  
endif
Sentencia= Sentencia + " ORDER BY CLAVE"
Ejecutar(Sentencia)




Que pasa con esto?

Al generar la sentencia en forma dinámica y con los valores de las variables ya incluidos en la sentencia, cada vez que se ejecute la sentencia va a ser una sentencia diferente, y por lo tanto va a tener que recompilarla y volver a evaluar el plan de ejecución de la misma. 
Hay pocas cosas que molesten mas a los DBA que no reutilizar los planes de ejecucion. 

Seria bueno poder contar con la posibilidad de generar en forma dinámica la sentencia, pero generarla con variables, pues puede ser utiles para los casos que una misma sentencia se ejecute muchas veces con el mismo "template" aunque la sentencia tenga when.  


NOTA1: Este post es el resultado de una de las tantas reuniones que tenemos con los DBA (administradores de la base de datos) de bases de datos Oracle (fundamentalmente) y SQL Server (son menos aguerridos). 

NOTA2: Es un tema que no domino, no conozco, no me interesa demasiado, pero como todo consultor que se precie, voy a opinar como si fuera un especialista del tema. 

NOTA3: Internamente este lo conocemos como el Problema del Binding. 
Podria llamarse también el dificil arte de dejar a los DBA contentos. 

(*) Aca hay un micropatrón que pide a los gritos ser descubierto. Seria bueno poder optar por generar o no la sentencia en forma dinamica, sin tener que cambiar el codigo del for each. 

Links que no debo perder (para no tener que buscarlos para la proxima reunion): 

Comentarios

Entradas más populares de este blog

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Aplicación monolítica o distribuida?

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.