una - Cursores rápidos de SQL Server
recorrer cursor sql server (8)
En general, se acepta que se debe evitar el uso de cursores en procedimientos almacenados siempre que sea posible (reemplazado con lógica basada en conjuntos, etc.). Si toma los casos en los que necesita iterar sobre algunos datos, y puede hacerlo de manera solo de lectura, ¿el cursor de avance rápido (solo lectura hacia adelante) es más o menos ineficiente que decir al tiempo que los ciclos? A partir de mis investigaciones, parece que la opción de cursor es generalmente más rápida y utiliza menos lecturas y tiempo de CPU. No hice ninguna prueba exhaustiva, pero ¿es esto lo que otros encuentran? Los cursores de este tipo (avance rápido) tienen una carga adicional o un recurso que podría ser costoso y que yo desconozco.
¿Se trata realmente de no utilizar cursores para evitar el uso de cursores cuando los enfoques basados en conjuntos están disponibles, y el uso de cursores actualizables, etc.
Gracias
"Si desea un cursor aún más rápido que el FAST FORWARD, use un cursor ESTÁTICO. Son más rápidos que FAST FORWARD. No son extremadamente rápidos, pero pueden hacer la diferencia".
¡No tan rapido! Según Microsoft: "Normalmente, cuando se producían estas conversiones, el tipo de cursor se degradaba a un tipo de cursor ''más caro''. Generalmente, un cursor (FAST) FORWARD-ONLY es el más eficiente, seguido por DYNAMIC, KEYSET y finalmente STATIC que es generalmente el menos eficiente ".
desde: http://blogs.msdn.com/b/mssqlisv/archive/2006/06/23/644493.aspx
Esta respuesta espera consolidar las respuestas dadas hasta la fecha.
1) Si es posible, utilice la lógica basada en el conjunto para sus consultas, es decir, intente y use simplemente SELECT
, INSERT
, UPDATE
o DELETE
con las cláusulas FROM
apropiadas o consultas anidadas, que casi siempre serán más rápidas.
2) Si lo anterior no es posible, entonces en SQL Server 2005+ los cursores FAST FORWARD
son eficientes y tienen un buen rendimiento y se deben usar con preferencia a los ciclos while.
La ''Mejor práctica'' de evitar cursores en SQL Server se remonta a SQL Server 2000 y versiones anteriores. La reescritura del motor en SQL 2005 abordó la mayoría de los problemas relacionados con los problemas de los cursores, particularmente con la introducción de la opción de avance rápido. Los cursores no son necesariamente peores que los basados en conjuntos y se usan extensamente y con éxito en Oracle PL / SQL (LOOP).
El ''generalmente aceptado'' al que se refiere es válido, pero ahora está desactualizado e incorrecto: asuma que los cursores de avance rápido se comportan como se anuncia y funciona. Haga algunas pruebas e investigaciones, basando sus hallazgos en SQL2005 y posterior
Las personas evitan el cursor porque generalmente son más difíciles de escribir que un simple ciclo de tiempo, sin embargo, un ciclo while puede ser costoso porque constantemente se seleccionan los datos de una tabla, temporal o de otro tipo.
Con un cursor, que es de solo lectura, los datos se guardan en la memoria y han sido diseñados específicamente para bucles.
Este artículo destaca que un cursor promedio se ejecuta 50 veces más rápido que un ciclo while.
Para responder las preguntas originales de Mile ...
Avance rápido, solo lectura, los cursores estáticos (cariñosamente conocidos como "Cursor de manguera de incendio") son típicamente tan rápidos o más rápidos que una tabla de temperatura equivalente y un ciclo de tiempo porque dicho cursor no es más que una tabla de temperatura y un ciclo de tiempo que ha sido optimizado un poco detrás de escena.
Para agregar a lo que Eric Z. Beard publicó en este hilo y para responder más a la pregunta de ...
"¿Se trata realmente de no utilizar cursores para evitar el uso de cursores cuando los enfoques basados en conjuntos están disponibles, y el uso de cursores actualizables, etc."
Sí. Con muy pocas excepciones, se necesita menos tiempo y menos código para escribir el código correcto basado en conjunto para hacer lo mismo que la mayoría de los cursores y tiene el beneficio adicional de utilizar muchos menos recursos y generalmente se ejecuta MUCHO más rápido que un cursor o un ciclo While. En términos generales, y con la excepción de ciertas tareas administrativas, deberían evitarse a favor de un código basado en conjuntos correctamente escrito. Hay, por supuesto, excepciones a cada "regla" pero, en el caso de Cursores, bucles While y otras formas de RBAR, la mayoría de las personas puede contar las excepciones con una mano sin usar todos los dedos. ;-)
También está la noción de "RBAR oculto". Este es un código que parece estar basado en conjuntos, pero en realidad no lo es. Este tipo de código "basado en conjuntos" es la razón por la cual ciertas personas han adoptado los métodos RBAR y dicen que están "OK". Por ejemplo, resolver el problema del total acumulado utilizando una subconsulta correlacionada agregada (SUM) con una desigualdad en él para generar el total acumulado no está realmente establecida en mi libro. En cambio, es RBAR con esteroides porque, para cada fila calculada, tiene que "tocar" repetidamente muchas otras filas a una tasa de N * (N + 1) / 2. Eso se conoce como "unión triangular" y es al menos la mitad de malo que una unión cartesiana completa (unión cruzada o "unión cuadrada").
Aunque MS ha realizado algunas mejoras en cómo funcionan los cursores desde SQL Server 2005, el término "Fast Cursor" sigue siendo un oxímoron en comparación con el código basado en conjuntos correctamente escrito. Eso también es cierto incluso en Oracle. Trabajé con Oracle durante 3 años en el pasado, pero mi trabajo consistía en mejorar el rendimiento del código existente. La mayoría de las mejoras realmente sustanciales se realizaron cuando convertí los cursores al código basado en conjuntos. Muchos trabajos que antes tardaban de 4 a 8 horas en ejecutarse se redujeron a minutos y, a veces, a segundos.
Puede evitar los cursores la mayor parte del tiempo, pero a veces es necesario.
Solo tenga en cuenta que FAST_FORWARD es DINÁMICO ... FORWARD_ONLY que puede usar con un cursor ESTÁTICO.
¡Trata de usarlo en el problema de Halloween para ver qué pasa!
IF OBJECT_ID(''Funcionarios'') IS NOT NULL
DROP TABLE Funcionarios
GO
CREATE TABLE Funcionarios(ID Int IDENTITY(1,1) PRIMARY KEY,
ContactName Char(7000),
Salario Numeric(18,2));
GO
INSERT INTO Funcionarios(ContactName, Salario) VALUES(''Fabiano'', 1900)
INSERT INTO Funcionarios(ContactName, Salario) VALUES(''Luciano'',2050)
INSERT INTO Funcionarios(ContactName, Salario) VALUES(''Gilberto'', 2070)
INSERT INTO Funcionarios(ContactName, Salario) VALUES(''Ivan'', 2090)
GO
CREATE NONCLUSTERED INDEX ix_Salario ON Funcionarios(Salario)
GO
-- Halloween problem, will update all rows until then reach 3000 !!!
UPDATE Funcionarios SET Salario = Salario * 1.1
FROM Funcionarios WITH(index=ix_Salario)
WHERE Salario < 3000
GO
-- Simulate here with all different CURSOR declarations
-- DYNAMIC update the rows until all of then reach 3000
-- FAST_FORWARD update the rows until all of then reach 3000
-- STATIC update the rows only one time.
BEGIN TRAN
DECLARE @ID INT
DECLARE TMP_Cursor CURSOR DYNAMIC
--DECLARE TMP_Cursor CURSOR FAST_FORWARD
--DECLARE TMP_Cursor CURSOR STATIC READ_ONLY FORWARD_ONLY
FOR SELECT ID
FROM Funcionarios WITH(index=ix_Salario)
WHERE Salario < 3000
OPEN TMP_Cursor
FETCH NEXT FROM TMP_Cursor INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT * FROM Funcionarios WITH(index=ix_Salario)
UPDATE Funcionarios SET Salario = Salario * 1.1
WHERE ID = @ID
FETCH NEXT FROM TMP_Cursor INTO @ID
END
CLOSE TMP_Cursor
DEALLOCATE TMP_Cursor
SELECT * FROM Funcionarios
ROLLBACK TRAN
GO
Si bien un cursor de avance rápido tiene algunas optimizaciones en Sql Server 2005, no es cierto que se acerquen a una consulta basada en conjunto en términos de rendimiento. Hay muy pocas situaciones donde la lógica del cursor no puede ser reemplazada por una consulta basada en conjuntos. Los cursores siempre serán intrínsecamente más lentos, debido en parte al hecho de que usted debe seguir interrumpiendo la ejecución para poder llenar sus variables locales.
Aquí hay algunas referencias, que solo serían la punta del iceberg si investigas este problema:
http://www.code-magazine.com/Article.aspx?quickid=060113
http://sqlblog.com/blogs/adam_machanic/archive/2007/10/13/cursors-run-just-fine.aspx
Si desea un cursor aún más rápido que FAST FORWARD, utilice un cursor STATIC. Son más rápidos que FAST FORWARD. No es extremadamente rápido pero puede marcar la diferencia.