miércoles, 1 de mayo de 2013

Count Incorrecto

Alguna que otra ves encontramos comportamientos extraños en algunas aplicaciones. A veces es un poco de desconocimiento, en otras malas prácticas y en otras algo de ambas.


Me encontré una aplicación en que en una de sus características simplemente debía retornar la cantidad de registros dado un campo de la tabla como filtro. Y el dato devuelto estaba erróneo. ¿Cómo algo tan simple y básico puede estar equivocado? 

Veamos un ejemplo: supongamos que tengo una Tabla con los siguientes registros:

Ahora realicemos un simple count(*) de los registros cuya Ubicacion sea 'CA'.


Cinco registros, esto es correcto. Pero todos sabemos que no es una buena práctica utilizar el asterisco(*) en una consulta por lo ineficiente que resulta la resolución de la misma. Entonces elegimos un campo para realizar el mismo count, digamos Descripcion.
Y el resultado es... erróneo. 

¿Por qué? Simplemente por que la implementación del count excluye de la cuenta los valores nulos resultantes de evaluar la expresión que estemos usando como parámetro para cada columna resultante del filtro. Así bien, existen dos registros con Ubicación 'CA' cuya Descripcion (la expresión a evaluar) es null y éstos no son tomados en cuenta en el resultado.

La solución es simple, utilicemos una columna en el que no haya posibilidad de valores nulos. En este particular el campo llave. O También podemos usar una expresión, por ejemplo 1, la cual evaluada por cada columna siempre será distinta de null.

Una ultima reflexión si somos un poco más inquisitivos y nos preguntamos ¿Cual de las tres sentencias que arrojan el resultado correcto es la más óptima? Podemos referirnos al plan de ejecución de cada sentencia.

Como podemos notar los tres planes de ejecución son exactamente iguales, entonces, podemos decir que las tres sentencias son equivalentes, por lo que, en este caso en particular, el usar el count(*) no significa mayor perdida de eficiencia de la consulta.

En lo personal prefiero el count(1) ya que no queda sujeta a ninguna columna de la tabla y su evaluación no depende de la implementación del motor de la base de datos. 

0 comentarios: