Ich habe diese Frage:
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;
Das Problem, das ich habe, ist, dass die Ausführung dieser Abfrage lange dauert. Ich weiß nicht, ob es möglich ist, dies parallel auszuführen, oder ob es einfacher wäre, einen Cursor in einer Pipeline-Funktion zu aktualisieren.
Was würdest du vorschlagen?
Dies sind alle Informationen, die ich für relevant halte.
Dies ist der Ausführungsplan der internen Auswahl:
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
Tabellendaten:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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 |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Dies ist das Skript der historischen Tabelle:
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)
);
Dies ist die andere Tabelle:
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
)
Die temporäre Tabelle ist das Ergebnis von FEE_SCHEDULE_HISTORICAL minus FEE_SCHEDULE
..AND EXISTS (SELECT NULL..
immer false zurückgeben? Wäre das -..AND NOT EXISTS (SELECT 1..
sinnvoller?SELECT NULL...
ist einfach verwirrend und sollte nicht verwendet werden (es sei denn, Sie verwenden aUNION
).fee_schedule (universe, fund_id, feetype_name, breakpoint_type, breakpoint_qty, low_breakpoint_amt)
. Vielleicht ist einer eingeschaltetuniverse, fund_id
bereits gut genug, um diesen FTS in einen Index-Scan umzuwandeln.Antworten:
Ich gehe davon aus, dass Ihre
FEE_SCHEDULE
Tabelle viel kleiner als dieFEE_SCHEDULE_HISTORICAL
Tabelle ist, also möchten Sie vielleichtEXISTS
etwas mehr ausnutzen . DasFEE_SCHEDULE
zeilenweise Eintauchen in die Tabelle kann eine relativ kostengünstige Operation sein, verglichen mit dem Verbinden mit allen Zeilen in der TabelleFEE_SCHEDULE_HISTORICAL
.Da die
ETL_FEE_SCH_TMP
Tabelle dasFEE_SCHEDULE_HISTORICAL
Minus istFEE_SCHEDULE
, können Sie das Update tatsächlich mit nur wenigenEXISTS
Anweisungen ohne alle Verknüpfungen durchführen und sparen sich die Mühe, die temporäre Tabelle zu erstellen. Sie brauchen die temporäre Tabelle nicht wirklich.Ich denke, das könnte einen Blick wert sein:
Erwägen Sie außerdem, der
FEE_SCHEDULE
Tabelle einen Index hinzuzufügen , ähnlich dem auf derFEE_SCHEDULE_HISTORICAL
. Das hilft dem Erklärungsplan wirklich weiter.quelle
Haben Sie versucht, SQL Tuning Advisor für Ihre Anweisung auszuführen? In der Regel werden fehlende Indizes, Statistiken, kostspielige Vorgänge usw. gefunden. Dies ist mit SQL Developer, z. Siehe http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/sqldev/r30/TuningAdvisor/TuningAdvisor.htm
quelle