ACCELERATING STORE PROCEDURE
Date: Thu, 19 Feb 2009 11:29:14 -0800 (PST)
Message-ID: <93be6817-3f0f-4282-b74b-312b558e8b6b_at_v15g2000vbb.googlegroups.com>
Hi everyone,
Hoping you are ok, i need your help to solve this query in order to make faster an stored procedure, it goes likes this:
Tables Sources -> SP procesing some data -> Tables Destiny (Results)
So my source's tables are
OM_DB.CDRS (86 fields and 30,000 rows average) OM_DB.COFETEL (8 fields and 62,000 rows average) OM_DB.CDRS_LISTED_ISDN_CAUSE_CODES (4 fields, 54 rows and this is acatalog, no index)
Those source tables with this indexes
CREATE INDEX PSA.CDRS_IX
ON OM_DB.CDRS(START_TIME,CALLED_PARTY_ON_DEST,CALL_SOURCE_REGID)
CREATE INDEX PSA.SX_CDRS
ON OM_DB.CDRS(ISDN_CAUSE_CODE,CALL_DURATION_INT)
CREATE INDEX PSA.COFETEL_IX
ON OM_DB.COFETEL(MODALIDAD)
CREATE INDEX PSA.COFETEL_SX
ON OM_DB.COFETEL(NIR_INICIAL,NIR_FINAL)
The destiny's tables are
om_db.CDRS_FINAL1 (9 fields, 5 rows per hour) om_db.CDRS_ISDN_CAUSE_CODE (5 fields, 50 rows per hour)
Those destiny tables with this indexes
CREATE UNIQUE INDEX PSA.IX_CDRS_FINAL1
ON OM_DB.CDRS_FINAL1(PMM_DATETIME,CALL_SOURCE_REGID)
CREATE UNIQUE INDEX PSA.IX_CDRS_ISDN_CAUSE_CODE
ON OM_DB.CDRS_ISDN_CAUSE_CODE
(PMM_DATETIME,CALL_SOURCE_REGID,ISDN_CAUSE_CODE)
I need run this procedure each 15 minutes and there are 30,000 rows
average on source OM_DB.CDRS, the execution time often exceed 15
minutes so i need to make better querys this is the sp:
Note: The DISTINCT(CALL_SOURCE_REGID) is 5 to 10 rows.
CREATE OR REPLACE PROCEDURE OM_DB.PR_MAKE_CDRS_FINAL1 IS
vPMM_DATETIME TIMESTAMP(3); vMAX_PMM_DATETIME TIMESTAMP(3); vEND_DATETIME TIMESTAMP(3);
vCALL_SOURCE_REGID VARCHAR2(30);
vTOTAL_CDRS_CLIENTE INT; vMIN_VALID_COFETEL INT; vMIN_INVALID_COFETEL INT; vMOVILES_VALIDOS INT; vMOVILES_INVALIDOS INT; vFIJOS_VALIDOS INT; vFIJOS_INVALIDOS INT; vNUMERIC_REASON_CODE INT; vTOTAL_ISDN_CAUSE INT; vCALL_DURATION_INT INT; v_rows_processed INT; count_violated INT;
CURSOR CL_CDR IS SELECT DISTINCT(CALL_SOURCE_REGID) FROM om_db.CDRS WHERE CALL_SOURCE_REGID IS NOT NULL;
CURSOR L_ISDN IS SELECT NUMERIC_REASON_CODE FROM om_db.CDRS_LISTED_ISDN_CAUSE_CODES ORDER BY NUMERIC_REASON_CODE;
BEGIN
dbms_output.enable(40000);
dbms_output.put_line('Inicio de procedimiento: ' || TO_CHAR
(sysdate, 'YYYY-MM-DD HH24:MI:SS'));
- Valida si existe informacion en la tabla de origen
count_violated := 0;
SELECT COUNT(*) INTO count_violated FROM om_db.CDRS;
IF (count_violated=0) THEN
dbms_output.put_line('No hay informacion en la tabla de
origen');
ELSE
SELECT TO_DATE(TO_CHAR(MIN(START_TIME),'YYYY-MM-DD HH24') || ':
00:00','YYYY-MM-DD HH24:MI:SS')
INTO vPMM_DATETIME FROM om_db.CDRS;
vEND_DATETIME := vPMM_DATETIME + 1/24;
SELECT TO_DATE(TO_CHAR(MAX(START_TIME),'YYYY-MM-DD HH24') || ':
59:59','YYYY-MM-DD HH24:MI:SS')
INTO vMAX_PMM_DATETIME FROM om_db.CDRS;
- ********************* PARA REPROCESAMIENTO UNICAMENTE
- ESPECIFICAR FECHA INICIAL Y FECHA FINAL
--vPMM_DATETIME := '2009-01-01 00:53:00';
--vEND_DATETIME := '2009-01-20 15:53:00';
--
WHILE (vPMM_DATETIME <= vMAX_PMM_DATETIME) LOOP OPEN CL_CDR; FETCH CL_CDR INTO vCALL_SOURCE_REGID; WHILE (CL_CDR%FOUND) LOOP vTOTAL_CDRS_CLIENTE := 0; vMIN_VALID_COFETEL := 0; vMIN_INVALID_COFETEL := 0; vMOVILES_VALIDOS := 0; vMOVILES_INVALIDOS := 0; vFIJOS_VALIDOS := 0; vFIJOS_INVALIDOS := 0; vTOTAL_ISDN_CAUSE := 0; vCALL_DURATION_INT := 0;- Obtener Total de CDRS por cliente SELECT COUNT(CALL_SOURCE_REGID) INTO vTOTAL_CDRS_CLIENTE FROM om_db.CDRS WHERE START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID;
- ********************* PARA REPROCESAMIENTO UNICAMENTE
v_rows_processed := 0; DELETE om_db.CDRS WHERE START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CALLED_PARTY_ON_DEST LIKE '%*%' AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID; v_rows_processed := sql%rowcount; vMIN_INVALID_COFETEL := v_rows_processed; -- Obtener MIN_VALID_COFETEL SELECT COUNT(*) INTO vMIN_VALID_COFETEL FROM ( SELECT A.*, B.* FROM om_db.CDRS A, om_db.cofetel B WHERE A.START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CAST(SUBSTR(A.CALLED_PARTY_ON_DEST,-10,10) AS NUMBER(*,0)) between B.NIR_INICIAL AND B.NIR_FINAL AND A.CALL_SOURCE_REGID = vCALL_SOURCE_REGID); -- Calcular el MIN_INVALID_COFETEL vMIN_INVALID_COFETEL := vTOTAL_CDRS_CLIENTE -vMIN_VALID_COFETEL;
- Obtener los MOVILES_VALIDOS SELECT COUNT(*) INTO vMOVILES_VALIDOS FROM ( SELECT A.*, B.* FROM om_db.CDRS A, om_db.cofetel B WHERE A.START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CAST(SUBSTR(A.CALLED_PARTY_ON_DEST,-10,10) AS NUMBER(*,0)) between B.NIR_INICIAL AND B.NIR_FINAL AND SUBSTR(A.CALLED_PARTY_ON_DEST,0,6) = '140521' AND A.CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND B.MODALIDAD = 'CPP');
- Obtener los MOVILES_INVALIDOS SELECT COUNT(*) INTO vMOVILES_INVALIDOS FROM ( SELECT A.*, B.* FROM om_db.CDRS A, om_db.cofetel B WHERE A.START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CAST(SUBSTR(A.CALLED_PARTY_ON_DEST,-10,10) AS NUMBER(*,0)) between B.NIR_INICIAL AND B.NIR_FINAL AND SUBSTR(A.CALLED_PARTY_ON_DEST,0,6) <> '140521' AND A.CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND B.MODALIDAD = 'CPP');
- Obtener los FIJOS_VALIDOS SELECT COUNT(*) INTO vFIJOS_VALIDOS FROM ( SELECT A.*, B.* FROM om_db.CDRS A, om_db.cofetel B WHERE A.START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CAST(SUBSTR(A.CALLED_PARTY_ON_DEST,-10,10) AS NUMBER(*,0)) between B.NIR_INICIAL AND B.NIR_FINAL AND SUBSTR(A.CALLED_PARTY_ON_DEST,0,5) = '14052' AND A.CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND B.MODALIDAD IN('FIJO','MPP'));
- Obtener los FIJOS_INVALIDOS SELECT COUNT(*) INTO vFIJOS_INVALIDOS FROM ( SELECT A.*, B.* FROM om_db.CDRS A, om_db.cofetel B WHERE A.START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CAST(SUBSTR(A.CALLED_PARTY_ON_DEST,-10,10) AS NUMBER(*,0)) between B.NIR_INICIAL AND B.NIR_FINAL AND SUBSTR(A.CALLED_PARTY_ON_DEST,0,5) <> '14052' AND A.CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND B.MODALIDAD IN('FIJO','MPP'));
v_rows_processed := 0; UPDATE om_db.CDRS_FINAL1 SET TOTAL_CDRS_CLIENTE = TOTAL_CDRS_CLIENTE + COALESCE
(vTOTAL_CDRS_CLIENTE,0),
MIN_VALID_COFETEL = MIN_VALID_COFETEL + COALESCE
(vMIN_VALID_COFETEL,0),
MIN_INVALID_COFETEL = MIN_INVALID_COFETEL + COALESCE(vMIN_INVALID_COFETEL,0), MOVILES_VALIDOS = MOVILES_VALIDOS + COALESCE
(vMOVILES_VALIDOS,0),
MOVILES_INVALIDOS = MOVILES_INVALIDOS + COALESCE
(vMOVILES_INVALIDOS,0),
FIJOS_VALIDOS = FIJOS_VALIDOS + COALESCE
(vFIJOS_VALIDOS,0),
FIJOS_INVALIDOS = FIJOS_INVALIDOS + COALESCE
(vFIJOS_INVALIDOS,0)
WHERE PMM_DATETIME = vPMM_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID; v_rows_processed := sql%rowcount; IF v_rows_processed = 0 THEN count_violated := 0; SELECT COUNT(PMM_DATETIME) INTO count_violated FROM om_db.CDRS_FINAL1 WHERE PMM_DATETIME = vPMM_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID; IF (count_violated=0) THEN INSERT INTO om_db.CDRS_FINAL1 VALUES( vPMM_DATETIME, vCALL_SOURCE_REGID, COALESCE(vTOTAL_CDRS_CLIENTE,0), COALESCE(vMIN_VALID_COFETEL,0), COALESCE(vMIN_INVALID_COFETEL,0), COALESCE(vMOVILES_VALIDOS,0), COALESCE(vMOVILES_INVALIDOS,0), COALESCE(vFIJOS_VALIDOS,0), COALESCE(vFIJOS_INVALIDOS,0) ); END IF; END IF; OPEN L_ISDN; FETCH L_ISDN INTO vNUMERIC_REASON_CODE; WHILE (L_ISDN%FOUND) LOOP -- Obtener vTOTAL_ISDN_CAUSE SELECT COUNT(ISDN_CAUSE_CODE) INTO vTOTAL_ISDN_CAUSE FROM om_db.CDRS WHERE START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND ISDN_CAUSE_CODE = vNUMERIC_REASON_CODE; -- Obtener vCALL_DURATION_INT de aquellos registros que sean mayor a 5 seg. SELECT SUM(CALL_DURATION_INT) INTO vCALL_DURATION_INT FROM om_db.CDRS WHERE START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND ISDN_CAUSE_CODE = vNUMERIC_REASON_CODE AND CALL_DURATION_INT >= 5; UPDATE om_db.CDRS_ISDN_CAUSE_CODE SET TOTAL_ISDN_CAUSE = TOTAL_ISDN_CAUSE + COALESCE
(vTOTAL_ISDN_CAUSE,0),
CALL_DURATION_INT = CALL_DURATION_INT + COALESCE(vCALL_DURATION_INT,0) WHERE PMM_DATETIME = vPMM_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND ISDN_CAUSE_CODE = vNUMERIC_REASON_CODE; v_rows_processed := sql%rowcount; IF v_rows_processed = 0 THEN count_violated := 0; SELECT COUNT(PMM_DATETIME) INTO count_violated FROM om_db.CDRS_ISDN_CAUSE_CODE WHERE PMM_DATETIME = vPMM_DATETIME AND CALL_SOURCE_REGID = vCALL_SOURCE_REGID AND ISDN_CAUSE_CODE = vNUMERIC_REASON_CODE; IF (count_violated=0) THEN INSERT INTO om_db.CDRS_ISDN_CAUSE_CODE VALUES( vPMM_DATETIME, vCALL_SOURCE_REGID, vNUMERIC_REASON_CODE, COALESCE(vTOTAL_ISDN_CAUSE,0), COALESCE(vCALL_DURATION_INT,0) ); END IF; END IF; FETCH L_ISDN INTO vNUMERIC_REASON_CODE; END LOOP; CLOSE L_ISDN; FETCH CL_CDR INTO vCALL_SOURCE_REGID; END LOOP; CLOSE CL_CDR; DELETE om_db.CDRS WHERE START_TIME BETWEEN vPMM_DATETIME AND vEND_DATETIME; COMMIT; vPMM_DATETIME := vPMM_DATETIME + 1/24; vEND_DATETIME := vPMM_DATETIME + 1/24; END LOOP; EXECUTE IMMEDIATE 'TRUNCATE TABLE om_db.CDRS'; COMMIT;
END IF;
dbms_output.put_line('Fin de procedimiento: ' || TO_CHAR(sysdate, 'YYYY-MM-DD HH24:MI:SS'));
END PR_MAKE_CDRS_FINAL1; Thanks in advanced Received on Thu Feb 19 2009 - 13:29:14 CST