Is there a way to fine-tune my Oracle SQL code below? All tables are residing in the same schema.
MERGE INTO W_PURCH_COST_F TGT USING
(SELECT
/*+ PARALLEL(8) */
cost.INTEGRATION_ID,
cost.X_RECEIVED_ON_DT,
COALESCE(gaap.ROW_WID,0) X_GAAP_EXCH_RATE_WID
FROM W_Purch_Cost_F_3955 cost
JOIN W_DAY_D wday
ON TRUNC(cost.X_RECEIVED_ON_DT)=TRUNC(wday.CALENDAR_DATE)
LEFT OUTER JOIN WC_GAAP_EXCH_RATE_G gaap
ON gaap.PERIOD =wday.PER_NAME_ENT_PERIOD
) SRC ON (TGT.INTEGRATION_ID = SRC.INTEGRATION_ID AND TGT.DATASOURCE_NUM_ID = 310)
WHEN MATCHED THEN
UPDATE SET TGT.X_GAAP_EXCH_RATE_WID = SRC.X_GAAP_EXCH_RATE_WID;
TGT is the target table and SRC is the source table, all residing in a staging environment and the same schema.
Plan hash value: 679420733
-----------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 18G| 256G| | 186K (5)| 00:00:15 | | | |
| 1 | MERGE | W_PURCH_COST_F | | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10002 | 18G| 10T| | 186K (5)| 00:00:15 | Q1,02 | P->S | QC (RAND) |
| 4 | VIEW | | | | | | | Q1,02 | PCWP | |
|* 5 | HASH JOIN RIGHT OUTER BUFFERED| | 18G| 10T| | 186K (5)| 00:00:15 | Q1,02 | PCWP | |
| 6 | TABLE ACCESS FULL | WC_GAAP_EXCH_RATE_G | 16261 | 269K| | 5 (0)| 00:00:01 | Q1,02 | PCWP | |
|* 7 | HASH JOIN | | 398M| 228G| 767M| 179K (1)| 00:00:15 | Q1,02 | PCWP | |
| 8 | PX RECEIVE | | 10M| 6014M| | 18997 (1)| 00:00:02 | Q1,02 | PCWP | |
| 9 | PX SEND HASH | :TQ10000 | 10M| 6014M| | 18997 (1)| 00:00:02 | Q1,00 | P->P | HASH |
| 10 | PX BLOCK ITERATOR | | 10M| 6014M| | 18997 (1)| 00:00:02 | Q1,00 | PCWC | |
|* 11 | TABLE ACCESS FULL | W_PURCH_COST_F | 10M| 6014M| | 18997 (1)| 00:00:02 | Q1,00 | PCWP | |
| 12 | PX RECEIVE | | 398M| 13G| | 28134 (2)| 00:00:03 | Q1,02 | PCWP | |
| 13 | PX SEND HASH | :TQ10001 | 398M| 13G| | 28134 (2)| 00:00:03 | Q1,01 | P->P | HASH |
|* 14 | HASH JOIN | | 398M| 13G| | 28134 (2)| 00:00:03 | Q1,01 | PCWP | |
| 15 | TABLE ACCESS FULL | W_DAY_D | 10790 | 210K| | 29 (0)| 00:00:01 | Q1,01 | PCWP | |
| 16 | PX BLOCK ITERATOR | | 383M| 6219M| | 27963 (2)| 00:00:03 | Q1,01 | PCWC | |
| 17 | TABLE ACCESS FULL | W_PURCH_COST_F_3955 | 383M| 6219M| | 27963 (2)| 00:00:03 | Q1,01 | PCWP | |
-----------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("GAAP"."PERIOD"(+)="WDAY"."PER_NAME_ENT_PERIOD")
7 - access("TGT"."INTEGRATION_ID"="COST"."INTEGRATION_ID")
11 - filter("TGT"."DATASOURCE_NUM_ID"=310)
14 - access(TRUNC(INTERNAL_FUNCTION("COST"."X_RECEIVED_ON_DT"))=TRUNC(INTERNAL_FUNCTION("WDAY"."CALENDAR_DATE")))
Note
-----
- dynamic statistics used: dynamic sampling (level=AUTO)
- Degree of Parallelism is 8 because of hint
- PDML is disabled in current session
Related
I want to aggregate data from table1 in all possible combinations of the 6 columns. Table1 has 60Million rows in it. The query is running for more than an hour and still not fetching any data. Need some help in tuning this
select /*+ parallel(a,8)*/
event_date,
a.COL1,
COL2,
COL3,
COL4,
COL5,
COL6,
count (distinct id) base_count,
count (distinct case when active_flg = 'Y' then id end) unique_active_cnt,
count (case when active_flg = 'Y' then id end) active_cnt,
GROUPING_ID (a.COL1,
COL2,
COL3,
COL4,
COL5,
COL6)
AS grp_id
from table1 partition (P2017_01) a
group by event_date,
cube (a.COL1,
COL2,
COL3,
COL4,
COL5,
COL6);
Explain plan for the above sql:-
Explain complete.
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3317440810
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 392K| 81M| | 96682 (4)| 00:00:08 | | | | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10001 | 392K| 20M| | 1157 (5)| 00:00:01 | | | Q1,01 | P->S | QC (RAND) |
| 4 | LOAD AS SELECT (TEMP SEGMENT MERGE)| SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | Q1,01 | PCWP | |
| 5 | SORT GROUP BY ROLLUP | | 392K| 20M| 293M| 1157 (5)| 00:00:01 | | | Q1,01 | PCWP | |
| 6 | PX RECEIVE | | 4040K| 208M| | 1121 (2)| 00:00:01 | | | Q1,01 | PCWP | |
| 7 | PX SEND HASH | :TQ10000 | 4040K| 208M| | 1121 (2)| 00:00:01 | | | Q1,00 | P->P | HASH |
| 8 | PX BLOCK ITERATOR | | 4040K| 208M| | 1121 (2)| 00:00:01 | 25 | 25 | Q1,00 | PCWC | |
| 9 | TABLE ACCESS FULL | TABLE1 | 4040K| 208M| | 1121 (2)| 00:00:01 | 25 | 25 | Q1,00 | PCWP | |
| 10 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 11 | PARTITION RANGE SINGLE | | 185K| 9224K| | 27366 (2)| 00:00:03 | 25 | 25 | | | |
| 12 | SORT GROUP BY ROLLUP | | 185K| 9224K| 278M| 27366 (2)| 00:00:03 | | | | | |
| 13 | TABLE ACCESS FULL | TABLE1 | 4040K| 196M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 14 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 15 | PARTITION RANGE SINGLE | | 32686 | 1595K| | 26191 (2)| 00:00:03 | 25 | 25 | | | |
| 16 | SORT GROUP BY ROLLUP | | 32686 | 1595K| 278M| 26191 (2)| 00:00:03 | | | | | |
| 17 | TABLE ACCESS FULL | TABLE1 | 4040K| 192M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 18 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 19 | PARTITION RANGE SINGLE | | 73 | 2336 | | 8374 (5)| 00:00:01 | 25 | 25 | | | |
| 20 | SORT GROUP BY ROLLUP | | 73 | 2336 | | 8374 (5)| 00:00:01 | | | | | |
| 21 | TABLE ACCESS FULL | TABLE1 | 4040K| 123M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 22 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 23 | PARTITION RANGE SINGLE | | 15408 | 707K| | 8374 (5)| 00:00:01 | 25 | 25 | | | |
| 24 | SORT GROUP BY ROLLUP | | 15408 | 707K| | 8374 (5)| 00:00:01 | | | | | |
| 25 | TABLE ACCESS FULL | TABLE1 | 4040K| 181M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 26 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 27 | PARTITION RANGE SINGLE | | 34 | 986 | | 8374 (5)| 00:00:01 | 25 | 25 | | | |
| 28 | SORT GROUP BY ROLLUP | | 34 | 986 | | 8374 (5)| 00:00:01 | | | | | |
| 29 | TABLE ACCESS FULL | TABLE1 | 4040K| 111M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 30 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 31 | PARTITION RANGE SINGLE | | 6 | 168 | | 8374 (5)| 00:00:01 | 25 | 25 | | | |
| 32 | SORT GROUP BY ROLLUP | | 6 | 168 | | 8374 (5)| 00:00:01 | | | | | |
| 33 | TABLE ACCESS FULL | TABLE1 | 4040K| 107M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 34 | LOAD AS SELECT | SYS_TEMP_0FDA4B738_9AA210CA | | | | | | | | | | |
| 35 | PARTITION RANGE SINGLE | | 3 | 75 | | 8374 (5)| 00:00:01 | 25 | 25 | | | |
| 36 | SORT GROUP BY ROLLUP | | 3 | 75 | | 8374 (5)| 00:00:01 | | | | | |
| 37 | TABLE ACCESS FULL | TABLE1 | 4040K| 96M| | 8081 (2)| 00:00:01 | 25 | 25 | | | |
| 38 | PX COORDINATOR | | | | | | | | | | | |
| 39 | PX SEND QC (RANDOM) | :TQ20000 | 392K| 81M| | 97 (3)| 00:00:01 | | | Q2,00 | P->S | QC (RAND) |
| 40 | VIEW | | 392K| 81M| | 97 (3)| 00:00:01 | | | Q2,00 | PCWP | |
| 41 | PX BLOCK ITERATOR | | 392K| 20M| | 97 (3)| 00:00:01 | | | Q2,00 | PCWC | |
| 42 | TABLE ACCESS FULL | SYS_TEMP_0FDA4B738_9AA210CA | 392K| 20M| | 97 (3)| 00:00:01 | | | Q2,00 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Note
-----
- Degree of Parallelism is 8 because of table property
53 rows selected.
IMAGE OF TOAD: query waits
WITH
NJ AS (SELECT CNATJUR FROM RE_CD.CDTD005_NATUR_JURIDICA WHERE DESCRICAO = 'Particulares' AND DTEND_VER = '9999-12-31 00:00' ),
PAISES AS (SELECT PAIS_BST FROM RE_CD.CDTD006_PAISES WHERE GRUPO_PAIS = 'RESTO UNIAO EUROPEIA' AND DTEND_VER = '9999-12-31 00:00' ),
GAR AS (SELECT /*+PARALLEL(4)*/ CCONTA, CREFERENCIA_IMP FROM RE_DM.DMTD002_GAR_CONTRATO WHERE TIPO_GAR = 'GAR REAL' AND TIPO_GAR2 = 'GAR DINERARIA' AND FLAG_PRIORIDADE = 1 AND IDVERSAO = (SELECT MAX(IDVERSAO) FROM RE_DM.DMTD001_VERSOES WHERE TABELA = 'RE_DM.DMTD002_GAR_CONTRATO' AND DTEND_VER = '9999-12-31 00:00' ) )
SELECT /*+PARALLEL(4)*/ MOROS.COD_PERIMETRO, MOROS.SOCIEDADE
FROM RE_DM.DMTF020_MOROS MOROS
INNER JOIN GAR ON MOROS.CCONTA = GAR.CCONTA AND MOROS.CREFERENCIA = GAR.CREFERENCIA_IMP
INNER JOIN NJ ON MOROS.COD_NATJUR = NJ.CNATJUR
INNER JOIN PAISES ON MOROS.COD_PAIS = PAISES.PAIS_BST
WHERE MOROS.IDVERSAO = 167
AND MOROS.SEGMENTO <> 'PC' AND MOROS.SEGMENTO <> 'LO' AND MOROS.SEGMENTO <> 'GA'
AND MOROS.SEGMENTO <> 'G1' AND MOROS.SEGMENTO <> 'G2' AND MOROS.SEGMENTO <> 'G3'
AND MOROS.INPUT = 'IMP'
AND MOROS.FLAG_MOROSIDADE = 0;
Plan hash value: 441958758
----------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 76752 | 16M| 22115 (1)| 00:01:07 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ20002 | 76752 | 16M| 22113 (1)| 00:01:07 | Q2,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN | | 76752 | 16M| 22113 (1)| 00:01:07 | Q2,02 | PCWP | |
| 4 | PX RECEIVE | | 42 | 1512 | 2 (0)| 00:00:01 | Q2,02 | PCWP | |
| 5 | PX SEND BROADCAST | :TQ20000 | 42 | 1512 | 2 (0)| 00:00:01 | Q2,00 | P->P | BROADCAST |
| 6 | PX BLOCK ITERATOR | | 42 | 1512 | 2 (0)| 00:00:01 | Q2,00 | PCWC | |
|* 7 | TABLE ACCESS FULL | CDTD006_PAISES | 42 | 1512 | 2 (0)| 00:00:01 | Q2,00 | PCWP | |
|* 8 | HASH JOIN | | 237K| 41M| 22110 (1)| 00:01:07 | Q2,02 | PCWP | |
| 9 | PX RECEIVE | | 23 | 1150 | 2 (0)| 00:00:01 | Q2,02 | PCWP | |
| 10 | PX SEND BROADCAST | :TQ20001 | 23 | 1150 | 2 (0)| 00:00:01 | Q2,01 | P->P | BROADCAST |
| 11 | PX BLOCK ITERATOR | | 23 | 1150 | 2 (0)| 00:00:01 | Q2,01 | PCWC | |
|* 12 | TABLE ACCESS FULL | CDTD005_NATUR_JURIDICA | 23 | 1150 | 2 (0)| 00:00:01 | Q2,01 | PCWP | |
| 13 | NESTED LOOPS | | | | | | Q2,02 | PCWP | |
| 14 | NESTED LOOPS | | 795K| 100M| 22105 (1)| 00:01:07 | Q2,02 | PCWP | |
| 15 | PX BLOCK ITERATOR | | | | | | Q2,02 | PCWC | |
|* 16 | TABLE ACCESS FULL | DMTD002_GAR_CONTRATO | 6357 | 341K| 4423 (1)| 00:00:14 | Q2,02 | PCWP | |
| 17 | SORT AGGREGATE | | 1 | 42 | | | Q2,02 | PCWP | |
| 18 | PX COORDINATOR | | | | | | | | |
| 19 | PX SEND QC (RANDOM) | :TQ10000 | 1 | 42 | | | Q1,00 | P->S | QC (RAND) |
| 20 | SORT AGGREGATE | | 1 | 42 | | | Q1,00 | PCWP | |
| 21 | PX BLOCK ITERATOR | | 1 | 42 | 2 (0)| 00:00:01 | Q1,00 | PCWC | |
|* 22 | TABLE ACCESS FULL | DMTD001_VERSOES | 1 | 42 | 2 (0)| 00:00:01 | Q1,00 | PCWP | |
|* 23 | INDEX RANGE SCAN | DMTF020_MOROS_INDEX2 | 21 | | 1 (0)| 00:00:01 | Q2,02 | PCWP | |
|* 24 | TABLE ACCESS BY INDEX ROWID| DMTF020_MOROS | 125 | 9750 | 3 (0)| 00:00:01 | Q2,02 | PCWP | |
----------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("MOROS"."COD_PAIS"="PAIS_BST")
7 - filter("GRUPO_PAIS"='RESTO UNIAO EUROPEIA' AND "DTEND_VER"='9999-12-31 00:00')
8 - access("MOROS"."COD_NATJUR"="CNATJUR")
12 - filter("DESCRICAO"='Particulares' AND "DTEND_VER"='9999-12-31 00:00')
16 - filter("TIPO_GAR2"='GAR DINERARIA' AND "TIPO_GAR"='GAR REAL' AND "FLAG_PRIORIDADE"=1 AND "IDVERSAO"= (SELECT
MAX(SYS_OP_CSR(SYS_OP_MSR(MAX("IDVERSAO")),0)) FROM "RE_DM"."DMTD001_VERSOES" "DMTD001_VERSOES" WHERE
"TABELA"='RE_DM.DMTD002_GAR_CONTRATO' AND "DTEND_VER"='9999-12-31 00:00'))
22 - filter("TABELA"='RE_DM.DMTD002_GAR_CONTRATO' AND "DTEND_VER"='9999-12-31 00:00')
23 - access("MOROS"."CREFERENCIA"="CREFERENCIA_IMP")
filter("MOROS"."CREFERENCIA" IS NOT NULL)
24 - filter("MOROS"."IDVERSAO"=167 AND "MOROS"."CCONTA" IS NOT NULL AND TO_NUMBER("MOROS"."FLAG_MOROSIDADE")=0 AND
"MOROS"."INPUT"='IMP' AND "MOROS"."SEGMENTO"<>'GA' AND "MOROS"."SEGMENTO"<>'G1' AND "MOROS"."SEGMENTO"<>'PC' AND
"MOROS"."SEGMENTO"<>'G2' AND "MOROS"."SEGMENTO"<>'G3' AND "MOROS"."SEGMENTO"<>'LO' AND "MOROS"."CCONTA"="CCONTA")
Note
-----
- dynamic sampling used for this statement (level=5)
- Degree of Parallelism is 4 because of hint
Does anyone see something fishy with this "explain plan"? I've added indexes, I ran statistics, rebuild indexes... the server is a laptop with 8gb ram, SSD hard drive and i7 cpu.
Any ideas?
Obviously, look for your full table scans, but they aren't always the culprit. The problem appears to be in the nested loops.
I would focus on DMTD002_GAR_CONTRATO, and perhaps place an index to eliminate the
full table scan; however, I suspect that the main problem may be in the subquery in the where clause that creates table alias "GAR".
It would be worth experimenting with a hardcoded value rather than a subquery to see if it improves performance.
(Posted on behalf of OP).
Our temp tablespace was super tiny. After increasing the size all things start to go faster and smoother. Thanks to all that helped.
I have two tables A & B. A has 6,760,636 records and B has 452,175,960 records. Here is the SELECT Statement I'm using:
SELECT /*+ parallel (T,1) */
T.*
FROM TABLE_A T,
TABLE_B P
WHERE T.DESTINATION = P.DESTINATION
AND T.SAIL_DATE = P.SAIL_DATE
AND T.PACKAGE_TYPE = P.PACKAGE_TYPE
AND T.CABIN_CATEGORY = P.CABIN_CATEGORY
AND T.BOOKING_SOURCE = P.BOOKING_SOURCE
AND T.FARE_TYPE = P.FARE_TYPE
AND T.POST_DATE = P.POST_DATE;
I tried creating the index on TABLE_A, but still it is not considering the INDEX and doing a FULL TABLE SCAN.
The EXPLAIN PLAN for above is
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6760K| 1805M| 747K (1)| | | |
| 1 | SORT AGGREGATE | | 1 | 48 | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| CL_PRICING_CONTROLS | 1 | 48 | 2 (0)| | | |
| 3 | INDEX RANGE SCAN | CL_PRICING_CONTROLS_IX3 | 1 | | 1 (0)| | | |
| 4 | PX COORDINATOR | | | | | | | |
| 5 | PX SEND QC (RANDOM) | :TQ10002 | 6760K| 1805M| 747K (1)| Q1,02 | P->S | QC (RAND) |
| 6 | HASH JOIN | | 6760K| 1805M| 747K (1)| Q1,02 | PCWP | |
| 7 | PX RECEIVE | | 6760K| 1437M| 1443 (1)| Q1,02 | PCWP | |
| 8 | PX SEND HASH | :TQ10001 | 6760K| 1437M| 1443 (1)| Q1,01 | P->P | HASH |
| 9 | PX BLOCK ITERATOR | | 6760K| 1437M| 1443 (1)| Q1,01 | PCWC | |
| 10 | TABLE ACCESS FULL | TMP_RES_PRICE_CONTROL_111 | 6760K| 1437M| 1443 (1)| Q1,01 | PCWP | |
| 11 | BUFFER SORT | | | | | Q1,02 | PCWC | |
| 12 | PX RECEIVE | | 450M| 23G| 746K (1)| Q1,02 | PCWP | |
| 13 | PX SEND HASH | :TQ10000 | 450M| 23G| 746K (1)| | S->P | HASH |
| 14 | INDEX FULL SCAN | CL_PRICING_CONTROLS_IX1 | 450M| 23G| 746K (1)| | | |
I tried parallel query on both tables as below
SELECT /*+ PARALLEL(T, 32) PARALLEL(P, 32)*/
T.*
FROM TABLE_A T,
TABLE_B P
WHERE T.DESTINATION = P.DESTINATION
AND T.SAIL_DATE = P.SAIL_DATE
AND T.PACKAGE_TYPE = P.PACKAGE_TYPE
AND T.CABIN_CATEGORY = P.CABIN_CATEGORY
AND T.BOOKING_SOURCE = P.BOOKING_SOURCE
AND T.FARE_TYPE = P.FARE_TYPE
AND T.POST_DATE = P.POST_DATE;
But this results in the EXPLAIN PLAN as below, where I see CPU with lower Cost, but still it is taking two hours.
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6760K| 1805M| 59345 (1)| | | |
| 1 | SORT AGGREGATE | | 1 | 48 | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| CL_PRICING_CONTROLS | 1 | 48 | 2 (0)| | | |
| 3 | INDEX RANGE SCAN | CL_PRICING_CONTROLS_IX3 | 1 | | 1 (0)| | | |
| 4 | PX COORDINATOR | | | | | | | |
| 5 | PX SEND QC (RANDOM) | :TQ10002 | 6760K| 1805M| 59345 (1)| Q1,02 | P->S | QC (RAND) |
| 6 | HASH JOIN BUFFERED | | 6760K| 1805M| 59345 (1)| Q1,02 | PCWP | |
| 7 | PX RECEIVE | | 6760K| 1437M| 1443 (1)| Q1,02 | PCWP | |
| 8 | PX SEND HASH | :TQ10000 | 6760K| 1437M| 1443 (1)| Q1,00 | P->P | HASH |
| 9 | PX BLOCK ITERATOR | | 6760K| 1437M| 1443 (1)| Q1,00 | PCWC | |
| 10 | TABLE ACCESS FULL | TMP_RES_PRICE_CONTROL_111 | 6760K| 1437M| 1443 (1)| Q1,00 | PCWP | |
| 11 | PX RECEIVE | | 450M| 23G| 57858 (1)| Q1,02 | PCWP | |
| 12 | PX SEND HASH | :TQ10001 | 450M| 23G| 57858 (1)| Q1,01 | P->P | HASH |
| 13 | PX BLOCK ITERATOR | | 450M| 23G| 57858 (1)| Q1,01 | PCWC | |
| 14 | TABLE ACCESS FULL | CL_PRICING_CONTROLS | 450M| 23G| 57858 (1)| Q1,01 | PCWP | |
Please look at your query, specifically at its WHERE clause. It consists entirely of join conditions. It could be rewritten using the ANSI-92 syntax to this:
SELECT /*+ parallel (T,1) */
T.*
FROM TABLE_A T
inner join TABLE_B P
on T.DESTINATION = P.DESTINATION
AND T.SAIL_DATE = P.SAIL_DATE
AND T.PACKAGE_TYPE = P.PACKAGE_TYPE
AND T.CABIN_CATEGORY = P.CABIN_CATEGORY
AND T.BOOKING_SOURCE = P.BOOKING_SOURCE
AND T.FARE_TYPE = P.FARE_TYPE
AND T.POST_DATE = P.POST_DATE;
So every row in each table has to be considered. Clearly full table scans are the only plausible access path.
Building a composite index on all columns in the JOIN clause is unlikely to change this. You are selecting all the columns from TABLE_A, so the database needs to visit the table anyway.
Unless the number of records in the intersection between the two tables is incredibly small it will be more efficient to read the tables in multi-block reads rather than index scans with table row look-ups. As it is, you're selecting almost one-in-six of all the rows in a half-billion row table. How would an index make that faster?
Incidentally, how did you decide on the degree of parallelism? How many CPUs does your server have? What other processes are running concurrently? What is the value of MAX_PARALLEL_SERVERS? Find out more.
Looking for a help in PT.
Attaching the psuedo query..
There are 3 tables used below all are having huge chunk of records
t2 ~ 10 million,
t1 ~ 15 million ,
t3 ~ 8 million
Used Parallel Hints . But not much help in cost.. Cost is shooting to more than 200k
(SELECT /*+ parallel (a,8) parallel (b,8)*/
DISTINCT B.ACCNT_NUM
FROM s1.t1 a, s2.t2 b
WHERE a.accnt_num = b.accnt_num
AND product_key IN (SELECT product_key FROM s3.t3 WHERE prod_type_cd = 'S')
AND a.active_flg = 'Y'
AND a.deleted_flg = 'N'
GROUP BY B.ACCNT_NUM, a.product_key
HAVING COUNT (*) > 1)
Plan:
| 0 | SELECT STATEMENT
| 1 | 54 | 204K (1)| 00:47:39 | | | | | | | 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10004 | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,04 | P->S | QC (RAND) |
| 3 | HASH UNIQUE | | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,04 | PCWP | |
| 4 | PX RECEIVE | | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,04 | PCWP | |
| 5 | PX SEND HASH | :TQ10003 | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,03 | P->P | HASH |
|* 6 | FILTER | | | | | | | | Q1,03 | PCWC | |
| 7 | HASH GROUP BY | | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,03 | PCWP | |
| 8 | PX RECEIVE | | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,03 | PCWP | |
| 9 | PX SEND HASH | :TQ10002 | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,02 | P->P | HASH |
| 10 | HASH GROUP BY | | 1 | 54 | 204K (1)| 00:47:39 | | | Q1,02 | PCWP | |
|* 11 | HASH JOIN | | 90476 | 4771K| 204K (1)| 00:47:39 | | | Q1,02 | PCWP | |
| 12 | PX RECEIVE | | 22572 | 462K| 66147 (1)| 00:15:27 | | | Q1,02 | PCWP | |
| 13 | PX SEND BROADCAST | :TQ10001 | 22572 | 462K| 66147 (1)| 00:15:27 | | | Q1,01 | P->P | BROADCAST |
|* 14 | TABLE ACCESS BY LOCAL INDEX ROWID| table 1 | 22572 | 462K| 66147 (1)| 00:15:27 | | | Q1,01 | PCWP | |
| 15 | NESTED LOOPS | | 135K| 4893K| 198K (1)| 00:46:19 | | | Q1,01 | PCWP | |
| 16 | BUFFER SORT | | | | | | | | Q1,01 | PCWC | |
| 17 | PX RECEIVE | | | | | | | | Q1,01 | PCWP | |
| 18 | PX SEND BROADCAST | :TQ10000 | | | | | | | | S->P | BROADCAST |
| 19 | SORT UNIQUE | | 6 | 96 | 3 (0)| 00:00:01 | | | | | |
|* 20 | TABLE ACCESS FULL | table 3 | 6 | 96 | 3 (0)| 00:00:01 | | | | | |
| 21 | PX PARTITION HASH ALL | | 65923 | | 207 (1)| 00:00:03 | 1 | 32 | Q1,01 | PCWC | |
|* 22 | INDEX RANGE SCAN | I_table1 | 65923 | | 207 (1)| 00:00:03 | 33 | 64 | Q1,01 | PCWP | |
| 23 | PX BLOCK ITERATOR | | 12M| 201M| 5738 (2)| 00:01:21 | | | Q1,02 | PCWC | |
| 24 | INDEX FAST FULL SCAN | I_table 2 | 12M| 201M| 5738 (2)| 00:01:21 | | | Q1,02 | PCWP | |
Regards
So the eye is drawn to this line of the Explain Plan:
|* 20 | TABLE ACCESS FULL | table 3 | 6 | 96 | 3 (0)| 00:00:01 | | | | | |
The optimizer on the other hand thinks it has six rows, and so regards it as a very cheap operation. The OP says that t3 has ~ 8 million rows. A Full Table Scan of that will be pretty expensive.
The optimizer is clever but relies on accurate table and index statistics. It seems a good place to start would be a review of the pertinent statistics, and refreshing the ones which are inaccurate. Find out more.
I am using a connect_by_level subquery in an Oracle database to supply dates to join with another table. The connect by level appears to be causing the query to run very slowly. Here is my slow query:
select t.code, d.month_end, count(*)
from device t,
(select add_months(trunc(sysdate, 'MM'), - (level - 1)) - 1 MONTH_END
from dual
connect by level <= 1) d
where (d.month_end between t.date and t.exp_date)
group by t.code, d.month_end
The slow query above took about 2 hours to run the other day. The query below which should be equivalent runs in less than 30 seconds:
select t.code, trunc(sysdate, 'MM') - 1 month_end, count(*)
from device t
where ((trunc(sysdate, 'MM') - 1) between t.date and t.exp_date)
group by t.code
Ultimately, I want the 1st query to return data for the past 24 months, but I need to figure out why it is running so slowly with only 1 month as the criteria. Any suggestions on what is causing the slow completion time with the connect by level query?
Edit to add explain plan output for slow query:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 520 | 65520 | 134K (1)| 00:00:03 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10006 | 520 | 65520 | 134K (1)| 00:00:03 | | | Q1,06 | P->S | QC (RAND) |
| 3 | HASH GROUP BY | | 520 | 65520 | 134K (1)| 00:00:03 | | | Q1,06 | PCWP | |
| 4 | PX RECEIVE | | 520 | 65520 | 134K (1)| 00:00:03 | | | Q1,06 | PCWP | |
| 5 | PX SEND HASH | :TQ10005 | 520 | 65520 | 134K (1)| 00:00:03 | | | Q1,05 | P->P | HASH |
| 6 | HASH GROUP BY | | 520 | 65520 | 134K (1)| 00:00:03 | | | Q1,05 | PCWP | |
|* 7 | HASH JOIN OUTER | | 520 | 65520 | 134K (1)| 00:00:03 | | | Q1,05 | PCWP | |
| 8 | PX RECEIVE | | 520 | 48880 | 134K (1)| 00:00:03 | | | Q1,05 | PCWP | |
| 9 | PX SEND HASH | :TQ10003 | 520 | 48880 | 134K (1)| 00:00:03 | | | Q1,03 | P->P | HASH |
|* 10 | HASH JOIN OUTER BUFFERED | | 520 | 48880 | 134K (1)| 00:00:03 | | | Q1,03 | PCWP | |
| 11 | PX RECEIVE | | | | | | | | Q1,03 | PCWP | |
| 12 | PX SEND HASH | :TQ10001 | | | | | | | Q1,01 | P->P | HASH |
| 13 | NESTED LOOPS | | | | | | | | Q1,01 | PCWP | |
| 14 | NESTED LOOPS | | 276 | 13800 | 50303 (0)| 00:00:01 | | | Q1,01 | PCWP | |
| 15 | BUFFER SORT | | | | | | | | Q1,01 | PCWC | |
| 16 | PX RECEIVE | | | | | | | | Q1,01 | PCWP | |
| 17 | PX SEND BROADCAST | :TQ10000 | | | | | | | | S->P | BROADCAST |
| 18 | VIEW | | 1 | 6 | 3 (0)| 00:00:01 | | | | | |
|* 19 | CONNECT BY WITHOUT FILTERING| | | | | | | | | | |
| 20 | FAST DUAL | | 1 | | 3 (0)| 00:00:01 | | | | | |
| 21 | PX PARTITION RANGE ALL | | 3898K| | 1656 (0)| 00:00:01 | 1 | 75 | Q1,01 | PCWC | |
|* 22 | INDEX RANGE SCAN | FTR_DT_IX1 | 3898K| | 1656 (0)| 00:00:01 | 1 | 75 | Q1,01 | PCWP | |
|* 23 | TABLE ACCESS BY LOCAL INDEX ROWID| FTR_DT | 276 | 12144 | 50300 (0)| 00:00:01 | 1 | 1 | Q1,01 | PCWP | |
| 24 | PX RECEIVE | | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,03 | PCWP | |
| 25 | PX SEND HASH | :TQ10002 | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,02 | P->P | HASH |
| 26 | PX BLOCK ITERATOR | | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,02 | PCWC | |
|* 27 | TABLE ACCESS STORAGE FULL | DTL_HIST_DT | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,02 | PCWP | |
| 28 | PX RECEIVE | | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,05 | PCWP | |
| 29 | PX SEND HASH | :TQ10004 | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,04 | P->P | HASH |
| 30 | PX BLOCK ITERATOR | | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,04 | PCWC | |
|* 31 | TABLE ACCESS STORAGE FULL | POINT_T | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,04 | PCWP | |
Predicate Information (identified by operation id):
---------------------------------------------------
7 - access("C"."CODE"="AP"."CODE"(+) AND "C"."POINT_ID"="AP"."POINT_ID"(+))
10 - access("CF"."P_ID"="C"."WTN"(+))
19 - filter(LEVEL<=1)
22 - access("CF"."DATE"<=INTERNAL_FUNCTION("D"."MONTH_END"))
23 - filter(UPPER("CF"."PLAN") LIKE '%DV%' AND ("CF"."FT_CODE"='7370' OR "CF"."FT_CODE"='7371' OR "CF"."FT_CODE"='7372' OR
"CF"."FT_CODE"='7373' OR "CF"."FT_CODE"='7374' OR "CF"."FT_CODE"='7380' OR "CF"."FT_CODE"='7380C' OR "CF"."FT_CODE"='7381' OR
"CF"."FT_CODE"='7381C' OR "CF"."FT_CODE"='7382' OR "CF"."FT_CODE"='7382C' OR "CF"."FT_CODE"='7383' OR "CF"."FT_CODE"='7384' OR
"CF"."FT_CODE"='7409' OR "CF"."FT_CODE"='7409C' OR "CF"."FT_CODE"='7410' OR "CF"."FT_CODE"='7410C' OR "CF"."FT_CODE"='TRKDV') AND
"CF"."EXP_DATE">=INTERNAL_FUNCTION("D"."MONTH_END"))
27 - storage("C"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "C"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
filter("C"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "C"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
31 - storage("AP"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "AP"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
filter("AP"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "AP"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
Note
-----
- dynamic sampling used for this statement (level=6)
- automatic DOP: Computed Degree of Parallelism is 8
Edit to add explain plan for faster query:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 278 | 33360 | 622K (1)| 00:00:11 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10005 | 278 | 33360 | 622K (1)| 00:00:11 | | | Q1,05 | P->S | QC (RAND) |
| 3 | HASH GROUP BY | | 278 | 33360 | 622K (1)| 00:00:11 | | | Q1,05 | PCWP | |
| 4 | PX RECEIVE | | 4034 | 472K| 622K (1)| 00:00:11 | | | Q1,05 | PCWP | |
| 5 | PX SEND HASH | :TQ10004 | 4034 | 472K| 622K (1)| 00:00:11 | | | Q1,04 | P->P | HASH |
|* 6 | HASH JOIN OUTER BUFFERED | | 4034 | 472K| 622K (1)| 00:00:11 | | | Q1,04 | PCWP | |
| 7 | PX RECEIVE | | 4034 | 346K| 621K (1)| 00:00:11 | | | Q1,04 | PCWP | |
| 8 | PX SEND HASH | :TQ10002 | 4034 | 346K| 621K (1)| 00:00:11 | | | Q1,02 | P->P | HASH |
|* 9 | HASH JOIN OUTER BUFFERED | | 4034 | 346K| 621K (1)| 00:00:11 | | | Q1,02 | PCWP | |
| 10 | PX RECEIVE | | 2140 | 94160 | 538K (1)| 00:00:09 | | | Q1,02 | PCWP | |
| 11 | PX SEND HASH | :TQ10000 | 2140 | 94160 | 538K (1)| 00:00:09 | | | Q1,00 | P->P | HASH |
| 12 | PX BLOCK ITERATOR | | 2140 | 94160 | 538K (1)| 00:00:09 | 1 | 75 | Q1,00 | PCWC | |
|* 13 | TABLE ACCESS STORAGE FULL| FTR_DT | 2140 | 94160 | 538K (1)| 00:00:09 | 1 | 75 | Q1,00 | PCWP | |
| 14 | PX RECEIVE | | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,02 | PCWP | |
| 15 | PX SEND HASH | :TQ10001 | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,01 | P->P | HASH |
| 16 | PX BLOCK ITERATOR | | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,01 | PCWC | |
|* 17 | TABLE ACCESS STORAGE FULL| DTL_HIST_DT | 7344K| 308M| 83875 (1)| 00:00:02 | | | Q1,01 | PCWP | |
| 18 | PX RECEIVE | | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,04 | PCWP | |
| 19 | PX SEND HASH | :TQ10003 | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,03 | P->P | HASH |
| 20 | PX BLOCK ITERATOR | | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,03 | PCWC | |
|* 21 | TABLE ACCESS STORAGE FULL | POINT_T | 108K| 3376K| 275 (0)| 00:00:01 | | | Q1,03 | PCWP | |
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("C"."CODE"="AP"."CODE"(+) AND "C"."POINT_ID"="AP"."POINT_ID"(+))
9 - access("CF"."P_ID"="C"."WTN"(+))
13 - storage(UPPER("CF"."PLAN") LIKE '%DV%' AND ("CF"."FT_CODE"='7370' OR "CF"."FT_CODE"='7371' OR "CF"."FT_CODE"='7372' OR
"CF"."FT_CODE"='7373' OR "CF"."FT_CODE"='7374' OR "CF"."FT_CODE"='7380' OR "CF"."FT_CODE"='7380C' OR "CF"."FT_CODE"='7381' OR
"CF"."FT_CODE"='7381C' OR "CF"."FT_CODE"='7382' OR "CF"."FT_CODE"='7382C' OR "CF"."FT_CODE"='7383' OR "CF"."FT_CODE"='7384'
OR "CF"."FT_CODE"='7409' OR "CF"."FT_CODE"='7409C' OR "CF"."FT_CODE"='7410' OR "CF"."FT_CODE"='7410C' OR
"CF"."FT_CODE"='TRKDV') AND "CF"."EXP_DATE">=TRUNC(SYSDATE#!,'fmmm')-1 AND "CF"."DATE"<=TRUNC(SYSDATE#!,'fmmm')-1)
filter(UPPER("CF"."PLAN") LIKE '%DV%' AND ("CF"."FT_CODE"='7370' OR "CF"."FT_CODE"='7371' OR "CF"."FT_CODE"='7372' OR
"CF"."FT_CODE"='7373' OR "CF"."FT_CODE"='7374' OR "CF"."FT_CODE"='7380' OR "CF"."FT_CODE"='7380C' OR "CF"."FT_CODE"='7381' OR
"CF"."FT_CODE"='7381C' OR "CF"."FT_CODE"='7382' OR "CF"."FT_CODE"='7382C' OR "CF"."FT_CODE"='7383' OR "CF"."FT_CODE"='7384'
OR "CF"."FT_CODE"='7409' OR "CF"."FT_CODE"='7409C' OR "CF"."FT_CODE"='7410' OR "CF"."FT_CODE"='7410C' OR
"CF"."FT_CODE"='TRKDV') AND "CF"."EXP_DATE">=TRUNC(SYSDATE#!,'fmmm')-1 AND "CF"."DATE"<=TRUNC(SYSDATE#!,'fmmm')-1)
17 - storage("C"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "C"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
filter("C"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "C"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
21 - storage("AP"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "AP"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
filter("AP"."EXP_DATE"(+)>=TRUNC(SYSDATE#!,'fmmm')-1 AND "AP"."DATE"(+)<=TRUNC(SYSDATE#!,'fmmm')-1)
Note
-----
- dynamic sampling used for this statement (level=6)
- automatic DOP: Computed Degree of Parallelism is 8
In first query Oracle is doing an index range scan on a large table and retrieving huge amounts of data on the first pass with access("CF"."DATE"<=INTERNAL_FUNCTION("D"."MONTH_END")). You can work around it by rewriting your select to be more like your fast one. It would be something like this -
select t.code, trunc(t.exp_date, 'MM') - 1 month_end, count(*)
from device t
where t.date < :report_period_end
and t.exp_date > :report_period_start
group by t.code, trunc(t.exp_date,'MM') - 1;
Also note that there are several potential problems with your original slow query:
A row where t.date and t.exp_date is more than 2 months apart will be counted multiple times.
Rows where t.date and t.exp_date has the same month will not be counted at all
You are comparing your dates to e.g. 2013.10.30 00:00:00. Results may be incorrect if your dates contain time data.