Actualización muy lenta

27/10/2004 - 10:51 por Javi | Informe spam
Siguiendo los consejos del grupo he realizado un proceso almacenado para
actualizar una tabla de más de 33 millones de registros, pero me funciona
muy lento, para actualizar 50.000 registros tarda dos horas y esto al
cliente le parece excesivo, así que os mando el código para ver si alguien
me ayuda a optimizarlo.
Este código es mi primera experiencia con cursores y procesos almacenados,
así que estoy convencido de que no debe ser la mejor forma de usarlos, así
que cualquier consejo será muy bien recibido.

Aquí va el código:

IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'get_ID_TP_TDA' AND type = 'P')
DROP PROCEDURE get_ID_TP_TDA

GO

CREATE PROCEDURE get_ID_TP_TDA
@TpTda varchar(1) OUTPUT

AS
DECLARE @Empr decimal
DECLARE @Tda decimal
DECLARE @Del decimal

SELECT TOP 1
@Empr = ID_EMPR,
@Tda = ID_TDA,
@Del = ID_DEL
FROM
Ventas
WHERE
ID_TP_TDA IS NULL

SELECT
@TpTda = ID_TP_TDA
FROM
Tiendas
WHERE
ID_EMPR = @Empr AND
ID_TDA = @Tda AND
ID_DEL = @Del
RETURN

GO

DECLARE MiCursor CURSOR
FOR
SELECT
ID_TP_TDA
FROM
Ventas
WHERE
ID_TP_TDA IS NULL
FOR UPDATE OF ID_TP_TDA

OPEN MiCursor
DECLARE @NUMERO_DE_REGISTROS_ACTUALIZADOS int
SET @NUMERO_DE_REGISTROS_ACTUALIZADOS = 0

DECLARE @HORA_INICIAL datetime
SET @HORA_INICIAL = GETDATE()



WHILE (@@FETCH_STATUS = 0 AND @NUMERO_DE_REGISTROS_ACTUALIZADOS < 50000) /*
< Numero de registros máximo a actualizar */

BEGIN
DECLARE @TipoTienda varchar(1)
DECLARE @TipoTiendaNULL varchar(1)

EXECUTE get_ID_TP_TDA
@TpTda = @TipoTienda OUTPUT

FETCH NEXT FROM MiCursor INTO @TipoTiendaNULL /* Evita que el resultado
se muestre en pantalla */

UPDATE
Ventas
SET
Ventas.ID_TP_TDA = @TipoTienda
FROM
Ventas
WHERE CURRENT OF MiCursor

SET @NUMERO_DE_REGISTROS_ACTUALIZADOS = @NUMERO_DE_REGISTROS_ACTUALIZADOS +
1
END

DECLARE @HORA_FINAL datetime
SET @HORA_FINAL = GETDATE()

SELECT @NUMERO_DE_REGISTROS_ACTUALIZADOS AS 'Número de registros',
@HORA_INICIAL as 'Hora de comienzo', @HORA_FINAL as 'Hora de finalización'

CLOSE MiCursor

DEALLOCATE MiCursor


Muchas gracias a todos

Javi
 

Leer las respuestas

#1 Liliana Sorrentino
27/10/2004 - 13:50 | Informe spam
Hola Javi,
No sé si el tope de 50.000 filas es obligatorio, pero sin ese control,
podrías probar de esta manera.

UPDATE
V1
SET
V1.ID_TP_TDA = V2.ID_TP_TDA
FROM #Ventas V1
INNER JOIN #Ventas V2
ON V1.ID_EMPR = V2.ID_EMPR AND V1.ID_TDA = V2.ID_TDA AND V1.ID_DEL V2.ID_DEL
WHERE
V1.ID_TP_TDA IS NULL AND V2.ID_TP_TDA IS NOT NULL

Saludos, Liliana.

"Javi" escribió en el mensaje
news:#
Siguiendo los consejos del grupo he realizado un proceso almacenado para
actualizar una tabla de más de 33 millones de registros, pero me funciona
muy lento, para actualizar 50.000 registros tarda dos horas y esto al
cliente le parece excesivo, así que os mando el código para ver si alguien
me ayuda a optimizarlo.
Este código es mi primera experiencia con cursores y procesos almacenados,
así que estoy convencido de que no debe ser la mejor forma de usarlos, así
que cualquier consejo será muy bien recibido.

Aquí va el código:

IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'get_ID_TP_TDA' AND type = 'P')
DROP PROCEDURE get_ID_TP_TDA

GO

CREATE PROCEDURE get_ID_TP_TDA
@TpTda varchar(1) OUTPUT

AS
DECLARE @Empr decimal
DECLARE @Tda decimal
DECLARE @Del decimal

SELECT TOP 1
@Empr = ID_EMPR,
@Tda = ID_TDA,
@Del = ID_DEL
FROM
Ventas
WHERE
ID_TP_TDA IS NULL

SELECT
@TpTda = ID_TP_TDA
FROM
Tiendas
WHERE
ID_EMPR = @Empr AND
ID_TDA = @Tda AND
ID_DEL = @Del
RETURN

GO

DECLARE MiCursor CURSOR
FOR
SELECT
ID_TP_TDA
FROM
Ventas
WHERE
ID_TP_TDA IS NULL
FOR UPDATE OF ID_TP_TDA

OPEN MiCursor
DECLARE @NUMERO_DE_REGISTROS_ACTUALIZADOS int
SET @NUMERO_DE_REGISTROS_ACTUALIZADOS = 0

DECLARE @HORA_INICIAL datetime
SET @HORA_INICIAL = GETDATE()



WHILE (@@FETCH_STATUS = 0 AND @NUMERO_DE_REGISTROS_ACTUALIZADOS < 50000)


/*
< Numero de registros máximo a actualizar */

BEGIN
DECLARE @TipoTienda varchar(1)
DECLARE @TipoTiendaNULL varchar(1)

EXECUTE get_ID_TP_TDA
@TpTda = @TipoTienda OUTPUT

FETCH NEXT FROM MiCursor INTO @TipoTiendaNULL /* Evita que el


resultado
se muestre en pantalla */

UPDATE
Ventas
SET
Ventas.ID_TP_TDA = @TipoTienda
FROM
Ventas
WHERE CURRENT OF MiCursor

SET @NUMERO_DE_REGISTROS_ACTUALIZADOS = @NUMERO_DE_REGISTROS_ACTUALIZADOS


+
1
END

DECLARE @HORA_FINAL datetime
SET @HORA_FINAL = GETDATE()

SELECT @NUMERO_DE_REGISTROS_ACTUALIZADOS AS 'Número de registros',
@HORA_INICIAL as 'Hora de comienzo', @HORA_FINAL as 'Hora de finalización'

CLOSE MiCursor

DEALLOCATE MiCursor


Muchas gracias a todos

Javi


Preguntas similares