Como ya todos sabemos el uso de esta técnica de programación tienen impactos negativos en la performance. Pero hay veces que no tenemos otra opción y si necesitamos usar algún que otro cursor
En este post veremos como optimizar a los cursores ya que hay diferentes formas de definirlos y según como lo hagamos podemos tener distintos tiempos de respuesta.
Para nuestras pruebas usaremos la base de datos AdventurweWorks2012 en donde haremos distintos cursores probando los tiempos de respuesta, básicamente la diferencia entre ellos es el tipo de cursor pero no así la consulta o proceso que hagan internamente el cual siempre es el mismo.
Cursor Default:
La primer prueba es usar los cursores por defecto o sea sin indicarle ningún atributo.
DECLAREcCURSOR
FOR
SELECTO.[object_id]
FROMsys.objectsASO
CROSSJOIN(SELECTTOP 1000 nameFROMsys.objects)ASO2
ORDERBYO.[object_id];
OPENc;
FETCHcINTO@i;
WHILE (@@FETCH_STATUS= 0)
BEGIN
SET@i+= 1;
FETCHcINTO@i;
END
CLOSEc;
DEALLOCATEc;
Cursor Local:
La segunda prueba es definir al cursor como local y correr el mismo proceso
DECLAREcCURSOR
LOCAL
FOR
SELECTO.[object_id]
FROMsys.objectsASO
CROSSJOIN(SELECTTOP 1000 nameFROMsys.objects)ASO2
ORDERBYO.[object_id];
OPENc;
FETCHcINTO@i;
WHILE (@@FETCH_STATUS= 0)
BEGIN
SET@i+= 1;
FETCHcINTO@i;
END
CLOSEc;
DEALLOCATEc;
Cursor Local y estático:
Ahora haremos la prueba definiéndolo como local y a su vez estático
DECLAREcCURSOR
LOCALSTATIC
FOR
SELECTO.[object_id]
FROMsys.objectsASO
CROSSJOIN(SELECTTOP 1000 nameFROMsys.objects)ASO2
ORDERBYO.[object_id];
OPENc;
FETCHcINTO@i;
WHILE (@@FETCH_STATUS= 0)
BEGIN
SET@i+= 1;
FETCHcINTO@i;
END
CLOSEc;
DEALLOCATEc;
Cursor Local y FAST_FORWARD:
La siguiente prueba es configurarlo como Local y FAST_FORWARD (Rápido y solo hacia adelante)
DECLAREcCURSOR
LOCALFAST_FORWARD
FOR
SELECTO.[object_id]
FROMsys.objectsASO
CROSSJOIN(SELECTTOP 1000 nameFROMsys.objects)ASO2
ORDERBYO.[object_id];
OPENc;
FETCHcINTO@i;
WHILE (@@FETCH_STATUS= 0)
BEGIN
SET@i+= 1;
FETCHcINTO@i;
END
CLOSEc;
DEALLOCATEc;
Cursor Local , Static Read_Only y Forward_Only:
Nuestra ultima prueba es configurarlo con todas estas opciones.
DECLAREcCURSOR
LOCALSTATICREAD_ONLYFORWARD_ONLY
FOR
SELECTO.[object_id]
FROMsys.objectsASO
CROSSJOIN(SELECTTOP 1000 nameFROMsys.objects)ASO2
ORDERBYO.[object_id];
OPENc;
FETCHcINTO@i;
WHILE (@@FETCH_STATUS= 0)
BEGIN
SET@i+= 1;
FETCHcINTO@i;
END
CLOSEc;
DEALLOCATEc;
Comparación de performance en tiempo:
Al correr todos los distintos procesos hemos tomado los tiempos donde arrojaron los siguientes resultados:
TEST | TIEMPO (Seg) |
CURSOR DEFAULT | 22 |
LOCAL | 20 |
LOCAL STATIC | 5 |
LOCAL FAST_FORWARD | 4 |
LOCAL STATIC READ_ONLY FORWARD_ONLY | 4 |
Conclusiones:
Si bien el uso de los cursores es una técnica poco recomendada por performance, es bueno considerar si tenemos que usarlos cuales son las mejores opciones de configuración para poder obtener los mejores tiempos de respuesta dentro de un cursor. Como se puede observar en los test hay una diferencia significativa entre los Cursores Default o locales y el resto