This is a discussion on Optimizar stored procedure within the Sybase forums, part of the Database Server Software category; --> Buenas Tardes: Alguien me podria decir como puedo hacer este stored procedure mas rapido?? estoy usando SYBASE y tarda ...
| |||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Buenas Tardes: Alguien me podria decir como puedo hacer este stored procedure mas rapido?? estoy usando SYBASE y tarda 00:13:47 en ejecutarse, necesito que tarde menos de 6 minutos en ejecutarse. Ojala alguien pueda ayudarme. Gracias. CREATE PROCEDURE PR_POP_UB_USRDETBYSIDNID @dINIT_DATE datetime=NULL, @dEND_DATE datetime=NULL AS DECLARE @dINIT_DATE_AUX DATETIME, @dEND_DATE_AUX DATETIME, @dINIT_DATE_COPY DATETIME, @dEND_DATE_COPY DATETIME, @dINIT_DATE_AUX_COPY DATETIME, @dEND_DATE_AUX_COPY DATETIME, @iCONTADOR INT, @CUR_SID VARCHAR(15), @CUR_NID VARCHAR(15), @iTOTAL INT, @iTOTAL_BAZ INT, @iTOTAL_EKT INT, @iTOTAL_IUS INT, @USRS_BAZ INT, @USRS_EKT INT, @USRS_IUS INT, @USRS_TOT INT, @iTOTAL_BAD INT, @INIT_PROC DATETIME, @END_PROC DATETIME, @ID_BEGIN INT, @ID_END INT, @CTL_ID_BEGIN INT, @CTL_DATE_ID_BEGIN DATETIME, @CTL_ID_END INT, @CTL_DATE_ID_END DATETIME SET NOCOUNT ON SELECT @INIT_PROC = (SELECT GETDATE()) -- VALIDO LA INTEGRIDAD DE LOS PARAMETROS IF(@dINIT_DATE IS NULL AND @dEND_DATE IS NOT NULL) OR (@dINIT_DATE IS NOT NULL AND @dEND_DATE IS NULL) BEGIN SELECT 'ERROR'=-1,'ERROR_DESC'= 'SOLO EXISTEN 2 POSIBILIDADES DE EJECUTAR ESTE SP. 1) ENVIE FECHA INICIAL Y FECHA FINAL 2) NO ENVIE NADA EL SP CONSULTARA A LA TABLA DE CONTROL' RETURN -1 END CREATE TABLE #TMP_UB_USRDETBYSIDNID2 ( ID_CSV int NOT NULL, PMM_DATETIME datetime NOT NULL, SID varchar(15) NULL, NID varchar(15) NULL, MINid varchar(15) NOT NULL ) CREATE INDEX IX_#TMP_UB_USRDETBYSIDNID2 ON #TMP_UB_USRDETBYSIDNID2(PMM_DATETIME, SID, NID) IF(@dINIT_DATE IS NULL) BEGIN -- CHECO EL DATE_ID_END DE LA TABLA DE CONTROL PARA SABER HASTA QUE FECHA ME QUEDE SELECT @dINIT_DATE = (SELECT DATE_ID_END FROM CTL_TABLES WHERE TABLE_NAME='UB_USRDETBYSIDNID') IF (@dINIT_DATE IS NULL) BEGIN -- SIGNIFICA QUE POR ALGUNA RAZON LA TABLA DE CONTROL NO SABE EN QUE FECHA NOS QUEDAMOS -- POR LO TANTO, VOY A LA TABLA DESTINO Y REVISO LA ULTIMA FECHA CAPTURADA SELECT @dINIT_DATE = (SELECT MAX(PMM_DATETIME) FROM UB_USRDETBYSIDNID) IF(@dINIT_DATE IS NULL) BEGIN -- SIGNIFICA QUE NO HAY INFORMACION CONFIABLE EN LA TABLA DESTINO SELECT 'ERROR'=-1,'ERROR_DESC'= 'AL CONSULTAR LA TABLA UB_USRDETBYSIDNID2 NO FUE POSIBLE ESTABLECER LA FECHA INICIAL DE BUSQUEDA PARA ESTA OPERACION' RETURN -1 END END -- DE AQUI RESTO 2 HORAS PARA ASEGURAR OBTENER LA INFORMACION MAS RECIENTE SELECT @dINIT_DATE = (SELECT DATEADD(hour,-2,@dINIT_DATE)) SELECT @dINIT_DATE=CONVERT(VARCHAR(2), DATEPART(mm, @dINIT_DATE)) + "/" + CONVERT(VARCHAR(2), DATEPART(dd, @dINIT_DATE)) + "/" + CONVERT(VARCHAR(4), DATEPART(yy, @dINIT_DATE)) + " " + CONVERT(VARCHAR(2), DATEPART(hh, @dINIT_DATE)) + ": 00:00" SELECT @dEND_DATE = (SELECT GETDATE()) END ELSE BEGIN -- SIGNIFICA QUE EL USUARIO HA ELEGIDO EL PERIODO DE TIEMPO EN EL CUAL BUSCARA INFORMACION EN LA TABLA CSV. -- VALIDO QUE LA FECHA INICIAL SEA MENOR O IGUAL A LA FECHA FINAL. IF(@dINIT_DATE > @dEND_DATE) BEGIN SELECT 'ERROR'=-1,'ERROR_DESC'= 'LA FECHA INICIAL ES MAYOR A LA FINAL, FECHAL INICIAL: ' + CONVERT(VARCHAR(19),CONVERT(VARCHAR(10), @dINIT_DATE,102) + ' ' + CONVERT(VARCHAR(8), @dINIT_DATE,108)) + ' FECHA FINAL: ' + CONVERT(VARCHAR(19),CONVERT(VARCHAR(10), @dEND_DATE,102) + ' ' + CONVERT(VARCHAR(8), @dEND_DATE,108)) RETURN -1 END END INSERT INTO #TMP_UB_USRDETBYSIDNID2 SELECT ID_CSV, PMM_DATETIME, SID, NID, MINid FROM CSV WHERE PMM_DATETIME BETWEEN @dINIT_DATE AND @dEND_DATE ORDER BY PMM_DATETIME IF @@ROWCOUNT = 0 BEGIN SELECT 'ERROR'=-1,'ERROR_DESC'= 'NO HAY INFORMACION DISPONIBLE EN EL PERIODO: ' + CONVERT(VARCHAR(19),CONVERT(VARCHAR(10), @dINIT_DATE,102) + ' ' + CONVERT(VARCHAR(8), @dINIT_DATE,108)) + ' AL ' + CONVERT(VARCHAR(19),CONVERT(VARCHAR(10), @dEND_DATE,102) + ' ' + CONVERT(VARCHAR(8), @dEND_DATE,108)) RETURN -1 END -- DEBO HACER LA BUSQUEDA DEL @ID_BEGIN MAS PEQUEÑO DENTRO DEL INTERVALO SELECT @ID_BEGIN = (SELECT MIN(ID_CSV) FROM #TMP_UB_USRDETBYSIDNID2) -- YA TENGO EL @ID_BEGIN, DEBO ENCONTRAR EL @ID_END SELECT @ID_END = (SELECT MAX(ID_CSV) FROM #TMP_UB_USRDETBYSIDNID2) -- AHORA ENCUENTRO LA FECHA INICIAL Y LA FINAL SELECT @dINIT_DATE = (SELECT MIN(PMM_DATETIME) FROM #TMP_UB_USRDETBYSIDNID2) SELECT @dEND_DATE = (SELECT MAX(PMM_DATETIME) FROM #TMP_UB_USRDETBYSIDNID2) -- RESPALDO LAS VARIABLES PARA QUE POSTERIORMENTE ACTUALIZE LA TABLA DE CONTROL SELECT @CTL_ID_BEGIN = @ID_BEGIN SELECT @CTL_DATE_ID_BEGIN = @dINIT_DATE SELECT @CTL_ID_END = @ID_END SELECT @CTL_DATE_ID_END = @dEND_DATE -- SE DEBE AJUSTAR EL @dINIT_DATE A LA HORA QUE PERTENEZCA. SELECT @dINIT_DATE_AUX = (SELECT CONVERT(DATETIME, (CONVERT(VARCHAR(10),@dINIT_DATE,102) + ' 00:00:00'))) SELECT @dEND_DATE_AUX = (SELECT CONVERT(DATETIME, (CONVERT(VARCHAR(10),@dINIT_DATE,102) + ' 00:04:59'))) WHILE (@dINIT_DATE_AUX <= @dEND_DATE_AUX) BEGIN IF ((@dINIT_DATE >= @dINIT_DATE_AUX) AND (@dINIT_DATE <= @dEND_DATE_AUX)) BEGIN SELECT @dINIT_DATE = @dINIT_DATE_AUX SELECT @dINIT_DATE_AUX = NULL BREAK END ELSE BEGIN SELECT @dINIT_DATE_AUX = (SELECT DATEADD(ss, 300,@dINIT_DATE_AUX)) SELECT @dEND_DATE_AUX = (SELECT DATEADD(ss, 299,@dINIT_DATE_AUX)) END END -- AJUSTO EL PRIMER INTERVALO DE BUSQUEDA SELECT @dEND_DATE_AUX = (SELECT DATEADD(ss,299,@dINIT_DATE)) SELECT @iCONTADOR = 0 CREATE TABLE #TMP2_UB_USRDETBYSIDNID2 ( ID_CSV int NOT NULL, PMM_DATETIME datetime NULL, SID varchar(15) NOT NULL, NID varchar(15) NOT NULL, MINid varchar(15) NOT NULL ) CREATE INDEX IX_#TMP2_UB_USRDETBYSIDNID2 ON #TMP2_UB_USRDETBYSIDNID2(PMM_DATETIME, SID, NID) -- INICIO CURSOR PARA OBTENER LAS ESTADISTICAS POR CADA UNO DE LOS SID/NID ACTIVOS EN LA TABLA SID_NID_CENTRALES DECLARE CURSIDS CURSOR FOR SELECT DISTINCT(SID) AS 'SIDS', NID AS 'NID' FROM SID_NID_CENTRALES WHERE BSTATUS = 1 ORDER BY SID OPEN CURSIDS FETCH CURSIDS INTO @CUR_SID, @CUR_NID WHILE (@@sqlstatus = 0) BEGIN -- RESPALDO LAS VARIABLES SELECT @dINIT_DATE_COPY = @dINIT_DATE, @dEND_DATE_COPY = @dEND_DATE, @dEND_DATE_AUX_COPY = @dEND_DATE_AUX -- INSERTO LOS REGISTROS QUE SEAN IGUALES AL SID Y NID CORRESPONDIENTES EN LA 2DA TABLA TEMPORAL INSERT INTO #TMP2_UB_USRDETBYSIDNID2 SELECT ID_CSV, PMM_DATETIME, @CUR_SID, @CUR_NID, MINid FROM #TMP_UB_USRDETBYSIDNID2 WHERE SID = @CUR_SID AND NID = @CUR_NID -- SE OBTIENE TODA LA INFORMACION DE LA TABLA DE ORIGEN DESDE EL INTERVALO INICIAL AJUSTADO HASTA EL INTERVALO FINAL EXACTO. WHILE (@dINIT_DATE <= @dEND_DATE) BEGIN SELECT @iTOTAL = 0, @iTOTAL_BAZ = 0, @iTOTAL_EKT = 0, @iTOTAL_IUS = 0, @USRS_BAZ = 0, @USRS_EKT = 0, @USRS_IUS = 0, @USRS_TOT = 0 SELECT @USRS_BAZ = COUNT(DISTINCT(A.MINid)) FROM #TMP2_UB_USRDETBYSIDNID2 A, usr_mines B WHERE A.PMM_DATETIME BETWEEN @dINIT_DATE AND @dEND_DATE_AUX AND A.SID = @CUR_SID AND A.NID = @CUR_NID AND B.corpo_id = 'BAZ' AND A.MINid = B.MIN_id SELECT @USRS_EKT = COUNT(DISTINCT(A.MINid)) FROM #TMP2_UB_USRDETBYSIDNID2 A, usr_mines B WHERE A.PMM_DATETIME BETWEEN @dINIT_DATE AND @dEND_DATE_AUX AND A.SID = @CUR_SID AND A.NID = @CUR_NID AND B.corpo_id = 'EKT' AND A.MINid = B.MIN_id DELETE #TMP2_UB_USRDETBYSIDNID2 FROM #TMP2_UB_USRDETBYSIDNID2 A, usr_mines B WHERE A.PMM_DATETIME BETWEEN @dINIT_DATE AND @dEND_DATE_AUX AND A.SID = @CUR_SID AND A.NID = @CUR_NID AND (B.corpo_id = 'EKT' OR B.corpo_id = 'BAZ') AND A.MINid = B.MIN_id SELECT @USRS_IUS = COUNT(DISTINCT(MINid)) FROM #TMP2_UB_USRDETBYSIDNID2 WHERE PMM_DATETIME BETWEEN @dINIT_DATE AND @dEND_DATE_AUX AND SID = @CUR_SID AND NID = @CUR_NID SELECT @USRS_TOT= ISNULL(@USRS_BAZ,0)+ISNULL(@USRS_EKT, 0)+ISNULL(@USRS_IUS,0) -- ACTUALIZA EL REGISTRO EXISTENTE CON LAS NUEVAS CANTIDADES OBTENIDAS. UPDATE UB_USRDETBYSIDNID SET SID = @CUR_SID, NID = @CUR_NID, USRS_BAZ = ISNULL(@USRS_BAZ,0), USRS_EKT = ISNULL(@USRS_EKT,0), USRS_IUS = ISNULL(@USRS_IUS,0), USRS_TOT = ISNULL(@USRS_TOT,0) WHERE PMM_DATETIME = @dINIT_DATE AND SID = @CUR_SID AND NID = @CUR_NID IF @@ROWCOUNT = 0 BEGIN -- SIGNIFICA QUE NO HAY INFORMACION EN LA TABLA DESTINO PARA EL INTERVALO DE TIEMPO EN CUESTION, ES NUEVO INSERT INTO UB_USRDETBYSIDNID VALUES(@dINIT_DATE,@CUR_SID,@CUR_NID,ISNULL(@USRS_ BAZ, 0),ISNULL(@USRS_EKT,0),ISNULL(@USRS_IUS,0),ISNULL( @USRS_TOT,0)) END DELETE #TMP2_UB_USRDETBYSIDNID2 WHERE PMM_DATETIME BETWEEN @dINIT_DATE AND @dEND_DATE_AUX AND SID = @CUR_SID AND NID = @CUR_NID -- INCREMENTO LAS VARIABLES. SELECT @iCONTADOR = @iCONTADOR + 1 SELECT @dINIT_DATE = (SELECT DATEADD(ss, 300,@dINIT_DATE)) SELECT @dEND_DATE_AUX = (SELECT DATEADD(ss, 299,@dINIT_DATE)) END -- RECUPERO LAS VARIABLES. SELECT @dINIT_DATE = @dINIT_DATE_COPY, @dEND_DATE = @dEND_DATE_COPY, @dEND_DATE_AUX = @dEND_DATE_AUX_COPY DELETE #TMP_UB_USRDETBYSIDNID2 WHERE SID = @CUR_SID AND NID = @CUR_NID FETCH CURSIDS INTO @CUR_SID, @CUR_NID -- LIMPIO LA TABLA LA 2DA TABLA TEMPORAL TRUNCATE TABLE #TMP2_UB_USRDETBYSIDNID2 END CLOSE CURSIDS DEALLOCATE cursor CURSIDS SELECT @END_PROC = (SELECT GETDATE()) SELECT 'ERROR'=0,'ERROR_DESC'= 'MOVIMIENTO EXITOSO SE REALIZARON ' + CONVERT(VARCHAR(12),@iCONTADOR) + ' INSERCIONES A LA TABLA UB_USRDETBYSIDNID2 ' + ' EL PERIODO DE EJECUCION FUE DE: ' + CONVERT(VARCHAR(19),CONVERT(VARCHAR(10),@INIT_PROC ,102) + ' ' + CONVERT(VARCHAR(8),@INIT_PROC,108)) + ' HASTA ' + CONVERT(VARCHAR(19),CONVERT(VARCHAR(10),@END_PROC, 102) + ' ' + CONVERT(VARCHAR(8),@END_PROC,108)) RETURN 0 |
| ||||
| > Alguien me podria decir como puedo hacer este stored procedure mas rapido?? < Check if you can replace creating temp tables by views or a simple SELECT statement and avoid cursors as they create performance bottlenecks - in most cases there is a set oriented solution possible. brgds Philipp Post |