J'ai cette requête:
UPDATE (
SELECT h.valid_through_dt, h.LAST_UPDATE_TMSTMP
FROM ETL_FEE_SCH_TMP d, FEE_SCHEDULE_HISTORICAL h
WHERE h.FUND_ID = d.FUND_ID
AND h.FEETYPE_NAME = d.FEETYPE_NAME
AND h.BREAKPOINT_TYPE = d.BREAKPOINT_TYPE
AND h.BREAKPOINT_QTY = d.BREAKPOINT_QTY
AND h.LOW_BREAKPOINT_AMT = d.LOW_BREAKPOINT_AMT
AND h.VALID_THROUGH = TO_DATE ('31-DEC-9999', 'dd-mon-yyyy')
AND h.universe = 'DC'
AND h.universe = d.universe
AND EXISTS
(
SELECT 1
FROM FEE_SCHEDULE s
WHERE s.FUND_ID = h.FUND_ID
AND s.FEETYPE_NAME = h.FEETYPE_NAME
AND s.BREAKPOINT_TYPE = h.BREAKPOINT_TYPE
AND s.BREAKPOINT_QTY = h.BREAKPOINT_QTY
AND s.LOW_BREAKPOINT_AMT = h.LOW_BREAKPOINT_AMT
AND s.universe = 'DC'
)
) updateTable
SET updateTable.VALID_THROUGH = (SYSDATE - 1),
updateTable.LAST_UPDATE_TMSTMP = SYSTIMESTAMP;
Le problème que j'ai est que cette requête prend beaucoup de temps à s'exécuter. Je ne sais pas s'il est possible d'exécuter cela en parallèle, ou il serait plus facile de mettre à jour un curseur dans une fonction de pipeline.
Que suggérerais-tu?
Ce sont toutes les informations que je pense qu'elles sont pertinentes.
Voici le plan d'exécution de la sélection interne:
Execution Plan
----------------------------------------------------------
Plan hash value: 57376096
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 306 | 8427 (1)| 00:01:42 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 1 | 306| 8427 (1)| 00:01:42 |
| 3 | MERGE JOIN CARTESIAN | | 1 | 192| 8426 (1)| 00:01:42 |
|* 4 | INDEX RANGE SCAN | SYS_C000666 | 1 | 96| 2 (0)| 00:00:01 |
| 5 | BUFFER SORT | | 3045K| 278M| 8425 (1)| 00:01:42 |
| 6 | SORT UNIQUE | | 3045K| 278M| 8425 (1)| 00:01:42 |
|* 7 | TABLE ACCESS FULL | FEE_SCHEDULE | 3045K| 278M| 8425 (1)| 00:01:42 |
|* 8 | INDEX RANGE SCAN | FEE_SCHDL_IDX1 | 1 | | 1 (0)| 00:00:01 |
|* 9 | TABLE ACCESS BY INDEX ROWID| FEE_SCHEDULE_HISTORICAL | 1 | 114 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."UNIVERSE"='DC')
7 - filter("S"."UNIVERSE"='DC')
8 - access("H"."UNIVERSE"='DC' AND "S"."FUND_ID"="H"."FUND_ID" AND
"S"."FEETYPE_NAME"="H"."FEETYPE_NAME" AND
"S"."BREAKPOINT_TYPE"="H"."BREAKPOINT_TYPE" AND
"S"."BREAKPOINT_QTY"="H"."BREAKPOINT_QTY" AND
"S"."LOW_BREAKPOINT_AMT"="H"."LOW_BREAKPOINT_AMT")
filter("H"."FUND_ID"="D"."FUND_ID" AND
"H"."FEETYPE_NAME"="D"."FEETYPE_NAME" AND
"H"."BREAKPOINT_TYPE"="D"."BREAKPOINT_UNIT_TY
Données du tableau:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UNIVERSE|FUND_ID |FEETYPE_NAME |BREAKPOINT_TYPE|BREAKPOINT_QTY|LOW_BREAKPOINT_AMT|HIGH_BREAKPOINT_AMT|FEE_PCT|FEE_SCHDL_SEQ_ID|GROUP_ID|LAST_UPDATE_TMSTMP |VALID_FROM|VALID_THROUGH|INSERT_TMSTMP |JOB_ID|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DC |DC9ZTPLPHO|DeferLoad |Percentage |4 |10000 |300000 |3.14 |780250 |null |1/4/2012 3:59:54 PM|6/23/2012 |12/31/9999 |1/5/2011 3:59:54 PM|666 |
DC |DCE86Y8XFU|RedemptionFee|Percentage |9 | 100 |100500 |7.67 |780251 |null |6/4/2012 4:49:54 PM|11/12/2011|12/31/9999 |8/17/2011 2:00:54 PM|666 |
DC |DCAYL0KONA|FrontLoad |Percentage |2 |50000 |601500 |5.00 |780252 |null |4/25/2012 4:49:54 PM|8/2/2012 |12/31/9999 |12/19/2012 9:59:00 PM|666 |
DC |DC9ZTPLPHO|DeferLoad |Percentage |7 |80000 |900000 |2.24 |780252 |null |4/25/2012 4:49:54 PM|8/2/2012 |12/31/9999 |12/19/2012 9:59:00 PM|666 |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Voici le script du tableau historique:
CREATE TABLE FEE_SCHEDULE_HISTORICAL
(
UNIVERSE VARCHAR2(2 BYTE) NOT NULL,
FUND_ID VARCHAR2(10 BYTE) NOT NULL,
FEETYPE_NAME VARCHAR2(75 BYTE),
BREAKPOINT_TYPE VARCHAR2(50 BYTE),
BREAKPOINT_QTY VARCHAR2(10 BYTE),
LOW_BREAKPOINT_AMT NUMBER(19,6),
HIGH_BREAKPOINT_AMT NUMBER(19,6),
FEE_PCT NUMBER(19,6),
FEE_SCHDL_SEQ_ID NUMBER NOT NULL,
GROUP_ID NUMBER,
LAST_UPDATE_TMSTMP DATE NOT NULL,
VALID_FROM DATE NOT NULL,
VALID_THROUGH DATE NOT NULL,
INSERT_TMSTMP DATE NOT NULL,
JOB_ID NUMBER NOT NULL
);
CREATE UNIQUE INDEX FEE_SCHDL_PK ON FEE_SCHEDULE_HISTORICAL(FEE_SCHDL_SEQ_ID);
CREATE UNIQUE INDEX FEE_SCHDL_HST_IDX ON FEE_SCHEDULE_HISTORICAL (
UNIVERSE,
FUND_ID,
FEETYPE_NAME,
BREAKPOINT_TYPE,
BREAKPOINT_QTY,
LOW_BREAKPOINT_AMT,
VALID_FROM,
JOB_ID
)
CREATE INDEX FEE_SCHEDULE_HST_IDX2 ON FEE_SCHEDULE_HISTORICAL(LAST_UPDATE_TMSTMP)
CREATE INDEX FEE_SCHEDULE_HST_IDX3 ON FEE_SCHEDULE_HISTORICAL(VALID_THROUGH)
ALTER TABLE FEE_SCHEDULE_HISTORICAL ADD (
CONSTRAINT FEE_SCHDL_PK
PRIMARY KEY
(FEE_SCHDL_SEQ_ID)
);
Voici l'autre tableau:
CREATE TABLE FEE_SCHEDULE
(
UNIVERSE VARCHAR2(2 BYTE) NOT NULL,
FUND_ID VARCHAR2(10 BYTE) NOT NULL,
FEETYPE_NAME VARCHAR2(75 BYTE),
BREAKPOINT_TYPE VARCHAR2(50 BYTE),
BREAKPOINT_QTY VARCHAR2(10 BYTE),
LOW_BREAKPOINT_AMT NUMBER(19,6),
HIGH_BREAKPOINT_AMT NUMBER(19,6),
FEE_PCT NUMBER(19,6),
JOB_RUN_ID NUMBER NOT NULL,
FILE_DATE DATE NOT NULL,
CYCLE_DATE DATE NOT NULL
)
La table temporaire est le résultat de FEE_SCHEDULE_HISTORICAL moins FEE_SCHEDULE
..AND EXISTS (SELECT NULL..
retournerait pas toujours faux? Serait-ce..AND NOT EXISTS (SELECT 1..
plus logique?SELECT NULL...
est tout simplement déroutant et ne doit pas être utilisé (sauf si vous utilisez unUNION
).fee_schedule (universe, fund_id, feetype_name, breakpoint_type, breakpoint_qty, low_breakpoint_amt)
. Peut-être que l'ununiverse, fund_id
est déjà assez bon pour transformer ce FTS en un balayage d'index.Réponses:
Je suppose que votre
FEE_SCHEDULE
table est beaucoup plus petite que laFEE_SCHEDULE_HISTORICAL
table, vous voudrez peut-être en exploiterEXISTS
un peu plus. Plonger dans laFEE_SCHEDULE
table ligne par ligne peut être une opération relativement bon marché par rapport à la joindre à toutes les lignes duFEE_SCHEDULE_HISTORICAL
.Étant donné que la
ETL_FEE_SCH_TMP
table est leFEE_SCHEDULE_HISTORICAL
moinsFEE_SCHEDULE
, vous pouvez réellement effectuer la mise à jour avec seulement quelquesEXISTS
instructions, sans toutes les jointures et vous éviter de créer la table temporaire. Vous n'avez pas vraiment besoin de la table temporaire.Je pense que cela pourrait valoir le coup d'oeil:
Pensez également à ajouter un index à la
FEE_SCHEDULE
table, similaire à celui duFEE_SCHEDULE_HISTORICAL
. Cela aide vraiment à expliquer le plan.la source
Avez-vous essayé d'exécuter SQL Tuning Advisor pour votre instruction? Il trouve généralement des index manquants, des statistiques, des opérations coûteuses, etc. Ceci est assez facile à faire en utilisant par exemple un développeur SQL. voir http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/sqldev/r30/TuningAdvisor/TuningAdvisor.htm
la source