Sidebar

En este artículo se muestra como cambiar el uso de un CURSOR por una sentencia WHILE, la cuál nos mejorara el performance en un 75%.

Desde mi punto de vista lo último que se debe de hacer en el diseño de una aplicación es hacer uso de los cursores, ya que consumen muchos recursos y son muy lentos. Así que debemos de tomarlos como la última alternativa en un desarrollo.

Supongamos que tenemos el siguiente cursor

DECLARE @item_category_id INT
DECLARE @order_id INT
DECLARE @purchase_order_id INT

DECLARE item_cursor CURSOR FAST_FORWARD FOR

SELECT
it.item_category_id
,ord.order_id
FROM dbo.item_categories it

INNER JOIN dbo.orders ord
ON ord.item_category_id = it.item_category_id

WHERE ord.order_date >= '1-sep-05'
and it.isSuspended != 1

OPEN item_cursor

FETCH NEXT FROM item_cursor INTO
@item_category_id
,@order_id

WHILE @@FETCH_STATUS = 0
BEGIN
EXEC dbo.usp_generate_purchase_order @item_category_id, @order_id, @purchase_order_id OUTPUT

/*
Codigo extra propio de nuestra aplicación
*/

FETCH NEXT FROM item_cursor INTO
@item-category_id
,@order_id
END

Ahora este es el codigo sin la necesidad de hacer uso de cursores y que nos da el mismo resultado usando un loop While.

--Declarando Variables
DECLARE @item_category_id INT
DECLARE @order_id INT
DECLARE @purchase_order_id INT

--Declarando tabla
DECLARE @item_table TABLE (primary_key INT IDENTITY(1,1) NOT NULL, --THE IDENTITY STATEMENT IS IMPORTANT!
item_category_id INT,
order_id INT
)

--Insertar los registros en nuestra tabla tal y como se seleccionaban en el Cursor
INSERT INTO @item_table
SELECT
it.item_category_id
,ord.order_id
FROM dbo.item_categories it

INNER JOIN dbo.orders ord
ON ord.item_category_id = it.item_category_id

WHERE ord.order_date >= '1-sep-05'
and it.isSuspended != 1

DECLARE @item_category_counter INT
DECLARE @loop_counter INT

SET @loop_counter = ISNULL((SELECT COUNT(*) FROM @item_table),0) -- Hacer el conteo de registros de nuestra tabla

SET @item_category_counter = 1

WHILE @loop_counter > 0 AND @item_category_counter <= @loop_counter
BEGIN
SELECT @item_category_id = item_category_id
,@order_id = order_id
FROM @item_table
WHERE primary_key = @item_category_counter

--Ahora pasar el item-category_id y order_id al store procedure
EXEC dbo.usp_generate_purchase_order @item_category_id, @order_id, @purchase_order_id OUTPUT

/*
Codigo extra de nuestra aplicación
*/

SET @item_category_counter = @item_category_counter + 1
END

Este cambio nos mejora el performance en un 75%, a comparación de un CURSO. Existen algunos casos que no son muy comunes, en el cuál es preferible hacer uso de un cursor, pero en un 99% solo te va a alentar tu aplicación, así que evita hacer uso de ellos.


Tips BD