Para poner las cosas en claro, creo que así como yo, casi todos prefieren evitar los cursores en la mayoría de los casos. ¿Son necesariamente malos? ¿Es una regla absoluta el evitar a un cursor? No. Algunas veces la operación que se necesita no puede ser hecha en base a conjuntos de datos, y un cursor puede ser desarrollado más rápido que un programa. Algunas veces es conocido que el avance en el bucle sólo involucra cientos de registros y no tomará mucho tiempo ejecutarse. Algunas veces estás trabajando con cursores ya existentes y sólo necesitas unos cambios menores, modificando el cursor en este escenario será más rápido que reescribir el procedimiento desde cero. Pero en general, yo intento evitar cursores mientras sea posible, y siempre busco alternativas para codificar la lógica.
Es posible remover a esos feos cursores de la lógica de datos, en algunos casos es más complicado. Vamos a ver un ejemplo de un cursor que tal vez deberíamos reemplazar. Por ejemplo un cursor utilizado para extraer información de estudiantes y que actualice la elección de transporte, un estudiante a la vez. La lógica es la siguiente:
1. Recuperar el nivel de grado del estudiante (inicial, primaria, o secundaria) en una variable.
2. Limpiar el código de transporte si el estudiante está dentro de la distancia adecuada para caminar a la escuela (la distancia es determinada en base también al nivel del estudiante).
3. Si el estudiante no está en una categoría particular (educación especial por ejemplo) y no está en un conjunto particular de colegios, establece el código de transporte a inelegible si los estudiantes están fuera de la zona.
4. Si el estudiante está en un programa de mediodía, actualizar el código de transporte para resaltar el hecho que el transporte será por mediodía.
5. Actualizar el código de transporte si el estudiante no reúne ninguno de los otros criterios.
La lógica utilizada en el cursor sería una enredada telaraña de sentencias de actualización, anidadas en una lógica muy compleja. Para hacerlo peor, digamos que hay 60 mil estudiantes, y esto podría tomar algo de 20 minutos para ejecutarse.
El Cursor
Veamos ahora como podría ser el cursor a utilizar para la operación que explicamos anteriormente.
DECLARE EstudiantesCursor CURSOR FAST_FORWARD FOR WHILE @@FETCH_STATUS = 0 -- para transporte (vive muy cerca de la escuela). AND NivelGrado = @NivelGrado)
--indicando el codigo de transporte a 'C0RR' y el UltimoUsuario a 'CScrpZ'
END |
Lo siguiente que hay que hacer para reemplazar el cursor con una sentencia SQL de conjuntos de datos es identificar las condiciones y bucles a repetir.
1. Encapsular las condiciones if/else que hay en el cursor en una tabla temporal con múltiples columnas tipo BIT. Para estas, mas de una de las condiciones pueden ser establecidas.
2. Utilizar la tabla temporal con las configuraciones tipo bit para determinar el código de transporte. Las sentencias de actualización simplemente modifican el código de transporte ý la última actualización al usuario, de modo que eso se realiza en una tabla temporal secundaria. En la lógica, el orden de las sentencias case realiza las actualizaciones en el cursor.
3. Utilizar los códigos de transporte que tenemos en la tabla 2 para realmente hacer las actualizaciones.
A continuación el SQL resultante:
-- Esta consulta llenará una tabla con diferentes campos tipo bit – distancia ciudad [SpedInelegibleParaC0RR] FROM —[lista de tablas] similar a las que están en la definición del cursor —usa los campos tipo bit para indicar el tipo de codigo de transporte SELECT ds.numeroEstudiante, ds.codigoTransporte AS 'curTransCodigo', --fuera de zona WHEN BilingualInelegibleForC0RR = 0 --ejecuta la actualizacion, indica los codigos de elegibilidad de transporte --[c5rr, c0rr, etc]. |
Esta consulta se ejecutará 10 o 100 veces más rápido que el cursor. ¿Porqué es tan lento el cursor? Porque cada estudiante es procesado uno a la vez. Y para empeorar las cosas, dentro de cada bucle del cursor, hay algo de cinco consultas a la vez, lo que si contamos con 60 mil estudiantes, serían algo de 300 mil consultas. Y sólo se necesitaban 3. Pero, y siempre hay un pero en la vida, la opción de usar un cursor mejora la depuración y lo hace más flexible que la opción de consultas. Siempre hay que decidir que es lo que queremos obtener: velocidad o simplicidad.
No hay comentarios:
Publicar un comentario