You Asked
Hi Tom,
Good Day.
When I was about to tune an application in the current company, I came across this statement in AWR report.
INSERT /*+ PARALLEL */ INTO TRADES VALUES (:B1 , :B2 , :B3 , :B4 , :B5 , :B6 , :B7 , :B8 , :B9 , :B10 , :B11 , :B12 , :B13 , :B14 , :B15 , :B16 , :B17 , :B18 , :B19 , :B20 , :B21 , :B22 , :B23 , :B24 , :B25 , :B26 , :B27 , :B28 , :B29 , :B30 , :B31 , :B32 , :B33 , :B34 , :B35 , :B36 , :B37 , :B38 , :B39 , :B40 , :B41 , :B42 , :B43 , :B44 , :B45 , :B46 , :B47 , :B48 , :B49 , :B50 , :B51 , :B52 , :B53 , :B54 , :B55 , :B56 , :B57 , :B58 , :B59 , :B60 , :B61 , :B62 , :B63 , :B64 , :B65 , :B66 , :B67 )
Number of Executions: 1
Number of Gets: 323,173.00
Number of Reads: 14,865.00
Elapsed Per Exec (s): 1640.40
a) What is the advantage of using PDML in this statement? Will it be more beneficial if I remove the Parallel Hint?
b) Is it okay to induce usage of indexes as hints? For example, consider the following (please pardon me for the improper formatting):
SQL Query:
SELECT /*+ INDEX(B PK_BFDT) INDEX(A PK_DOMT) INDEX(D IDUPT01) INDEX(C IDOMT_L_02) */
A.DOC_ID ||' '||A.DOC_NME||' '||TO_CHAR(A.CRT_TS,'MM/DD/YYYY HH24:MI:SS')
||' '||TO_CHAR(A.LAST_UPDT_TS,'MM/DD/YYYY HH24:MI:SS') ||' '||A.DOCUMENTSTAT_DOCUMENTSTATU_FK
||' '||A.DOC_EXHAUST_IND||' '||A.DOCINPUTSOUR_DOCUMENTINPUT_FK||' '||A.INTRODUCINGBROKER_IBD_CODE_FK
||' '||A.DOC_IM_CAPTURE_BTCH_NM||' '||A.DOC_SPPR_IN||' '||A.NUM_OF_PG||' '||B.DOC_DESC||' '||B.DOC_TY
||' '||B.BUSINESSFUNC_BUSINESSFUNCT_FK||' '||A.STRG_PATH||' '||A.DOCUMENTFORMAT_FORMATCODE_FK||' '||A.OFC_ID
||' '||A.IP_ID||' '||A.DOC_PVT_IN||' '||A.DOC_PVT_USR_ID||' '||A.DOC_SIZE_BYTE_CT||' '||A.IM_DOC_VER_ENBL_IN
||' '||D.EXT_APPL_SYS_TRANS||' '||D.NTRSE_RQST_ID||' '||D.EXC_ITM_ID||' ' AS RESULT FROM
BFDT_BUS_FUNC_DOC_TY B,DUPT_DOC_UNDER_PROC D,DOMT_DOC A,DOMT_DOC_ACCOUNTS_L C WHERE C.TARG_ACCTNUM = '5NX758200'
AND C.BUS_FUNC_GRP_TX = 'Pershing' AND A.DOC_ID = C.SRC_DOC_ID AND A.BUS_FUNC_GRP_TX = 'Pershing' AND
A.DOCUMENTSTAT_DOCUMENTSTATU_FK IN ('51','50') AND A.DOC_EXHAUST_IND IS NULL AND
A.BUSINESSFUNCDOCTY_OBJECTID_FK IN (1441,1534) AND B.OBJ_ID = A.BUSINESSFUNCDOCTY_OBJECTID_FK AND
D.DOC_ID(+) = A.DOC_ID ORDER BY A.CRT_TS DESC
Execution Plan
----------------------------------------------------------
Plan hash value: 1105676031
-------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows |Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 213 | 26 (4)| 00:00:01 | | |
| 1 | SORT ORDER BY | | 1 | 213 | 26 (4)| 00:00:01 | | |
| 2 | NESTED LOOPS OUTER | | 1 | 213 | 25 (0)| 00:00:01 | | |
|* 3 | HASH JOIN | | 1 | 168 | 23 (0)| 00:00:01 | | |
| 4 | NESTED LOOPS | | 8 | 1048 | 20 (0)| 00:00:01 | | |
| 5 | PARTITION LIST SINGLE | | 8 | 200 | 7 (0)| 00:00:01 | KEY | KEY |
| 6 | TABLE ACCESS BY LOCAL INDEX ROWID| DOMT_DOC_ACCOUNTS_L | 8 | 200 | 7 (0)| 00:00:01 | 1 | 1 |
|* 7 | INDEX RANGE SCAN | IDOMT_L_02 | 8 | | 3 (0)| 00:00:01 | 1 | 1 |
|* 8 | TABLE ACCESS BY GLOBAL INDEX ROWID| DOMT_DOC | 1 | 106 | 2 (0)| 00:00:01 | 1 | 1 |
|* 9 | INDEX UNIQUE SCAN | PK_DOMT | 1 | | 1 (0)| 00:00:01 | | |
| 10 | INLIST ITERATOR | | | | | | | |
| 11 | TABLE ACCESS BY INDEX ROWID | BFDT_BUS_FUNC_DOC_TY | 2 | 74 | 3 (0)| 00:00:01 | | |
|* 12 | INDEX UNIQUE SCAN | PK_BFDT | 2 | | 2 (0)| 00:00:01 | | |
| 13 | TABLE ACCESS BY INDEX ROWID | DUPT_DOC_UNDER_PROC | 1 | 45 | 2 (0)| 00:00:01 | | |
|* 14 | INDEX RANGE SCAN | IDUPT01 | 1 | | 1 (0)| 00:00:01 | | |
-------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("B"."OBJ_ID"="A"."BUSINESSFUNCDOCTY_OBJECTID_FK")
7 - access("C"."BUS_FUNC_GRP_TX"='Pershing' AND "C"."TARG_ACCTNUM"='5NX758200')
8 - filter(("A"."BUSINESSFUNCDOCTY_OBJECTID_FK"=1441 OR "A"."BUSINESSFUNCDOCTY_OBJECTID_FK"=1534) AND
"A"."DOC_EXHAUST_IND" IS NULL AND ("A"."DOCUMENTSTAT_DOCUMENTSTATU_FK"='50' OR
"A"."DOCUMENTSTAT_DOCUMENTSTATU_FK"='51') AND "A"."BUS_FUNC_GRP_TX"='Pershing')
9 - access("A"."DOC_ID"="C"."SRC_DOC_ID")
12 - access("B"."OBJ_ID"=1441 OR "B"."OBJ_ID"=1534)
14 - access("D"."DOC_ID"(+)="A"."DOC_ID")
If I remove the hints and execute as follows:
SELECT A.DOC_ID ||' '||A.DOC_NME||' '||TO_CHAR(A.CRT_TS,'MM/DD/YYYY HH24:MI:SS')
||' '||TO_CHAR(A.LAST_UPDT_TS,'MM/DD/YYYY HH24:MI:SS') ||' '||A.DOCUMENTSTAT_DOCUMENTSTATU_FK
||' '||A.DOC_EXHAUST_IND||' '||A.DOCINPUTSOUR_DOCUMENTINPUT_FK||' '||A.INTRODUCINGBROKER_IBD_CODE_FK
||' '||A.DOC_IM_CAPTURE_BTCH_NM||' '||A.DOC_SPPR_IN||' '||A.NUM_OF_PG||' '||B.DOC_DESC||' '||B.DOC_TY
||' '||B.BUSINESSFUNC_BUSINESSFUNCT_FK||' '||A.STRG_PATH||' '||A.DOCUMENTFORMAT_FORMATCODE_FK||' '||A.OFC_ID
||' '||A.IP_ID||' '||A.DOC_PVT_IN||' '||A.DOC_PVT_USR_ID||' '||A.DOC_SIZE_BYTE_CT||' '||A.IM_DOC_VER_ENBL_IN
||' '||D.EXT_APPL_SYS_TRANS||' '||D.NTRSE_RQST_ID||' '||D.EXC_ITM_ID||' ' AS RESULT FROM
BFDT_BUS_FUNC_DOC_TY B,DUPT_DOC_UNDER_PROC D,DOMT_DOC A,DOMT_DOC_ACCOUNTS_L C WHERE C.TARG_ACCTNUM = '5NX758200'
AND C.BUS_FUNC_GRP_TX = 'Pershing' AND A.DOC_ID = C.SRC_DOC_ID AND A.BUS_FUNC_GRP_TX = 'Pershing' AND
A.DOCUMENTSTAT_DOCUMENTSTATU_FK IN ('51','50') AND A.DOC_EXHAUST_IND IS NULL AND
A.BUSINESSFUNCDOCTY_OBJECTID_FK IN (1441,1534) AND B.OBJ_ID = A.BUSINESSFUNCDOCTY_OBJECTID_FK AND
D.DOC_ID(+) = A.DOC_ID ORDER BY A.CRT_TS DESC
Execution Plan
----------------------------------------------------------
Plan hash value: 1105676031
-------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows |Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 213 | 26 (4)| 00:00:01 | | |
| 1 | SORT ORDER BY | | 1 | 213 | 26 (4)| 00:00:01 | | |
| 2 | NESTED LOOPS OUTER | | 1 | 213 | 25 (0)| 00:00:01 | | |
|* 3 | HASH JOIN | | 1 | 168 | 23 (0)| 00:00:01 | | |
| 4 | NESTED LOOPS | | 8 | 1048 | 20 (0)| 00:00:01 | | |
| 5 | PARTITION LIST SINGLE | | 8 | 200 | 7 (0)| 00:00:01 | KEY | KEY |
| 6 | TABLE ACCESS BY LOCAL INDEX ROWID| DOMT_DOC_ACCOUNTS_L | 8 | 200 | 7 (0)| 00:00:01 | 1 | 1 |
|* 7 | INDEX RANGE SCAN | IDOMT_L_02 | 8 | | 3 (0)| 00:00:01 | 1 | 1 |
|* 8 | TABLE ACCESS BY GLOBAL INDEX ROWID| DOMT_DOC | 1 | 106 | 2 (0)| 00:00:01 | 1 | 1 |
|* 9 | INDEX UNIQUE SCAN | PK_DOMT | 1 | | 1 (0)| 00:00:01 | | |
| 10 | INLIST ITERATOR | | | | | | | |
| 11 | TABLE ACCESS BY INDEX ROWID | BFDT_BUS_FUNC_DOC_TY | 2 | 74 | 3 (0)| 00:00:01 | | |
|* 12 | INDEX UNIQUE SCAN | PK_BFDT | 2 | | 2 (0)| 00:00:01 | | |
| 13 | TABLE ACCESS BY INDEX ROWID | DUPT_DOC_UNDER_PROC | 1 | 45 | 2 (0)| 00:00:01 | | |
|* 14 | INDEX RANGE SCAN | IDUPT01 | 1 | | 1 (0)| 00:00:01 | | |
-------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("B"."OBJ_ID"="A"."BUSINESSFUNCDOCTY_OBJECTID_FK")
7 - access("C"."BUS_FUNC_GRP_TX"='Pershing' AND "C"."TARG_ACCTNUM"='5NX758200')
8 - filter(("A"."BUSINESSFUNCDOCTY_OBJECTID_FK"=1441 OR "A"."BUSINESSFUNCDOCTY_OBJECTID_FK"=1534) AND
"A"."DOC_EXHAUST_IND" IS NULL AND ("A"."DOCUMENTSTAT_DOCUMENTSTATU_FK"='50' OR
"A"."DOCUMENTSTAT_DOCUMENTSTATU_FK"='51') AND "A"."BUS_FUNC_GRP_TX"='Pershing')
9 - access("A"."DOC_ID"="C"."SRC_DOC_ID")
12 - access("B"."OBJ_ID"=1441 OR "B"."OBJ_ID"=1534)
14 - access("D"."DOC_ID"(+)="A"."DOC_ID")
Surprisingly, both execution plans are same and please note that the PLAN ID are also same. Optimizer mode is ALL_ROWS. Table and Index statistics are collected every day using DBMS_STATS
Could you please explain on why the optimizer is choosing the same plan for both the statements? Also, as you have suggested that using hints should be avoided, in this case, what should I do?
Well, I have posted two questions. I will stop with this and post the remaining questions later.
Thanks
Hari
and Tom said...
... INSERT /*+ PARALLEL */ INTO TRADES VALUES (:B1 , :B2 , :B3 , :B4 , :B5 , :B6 , :B7 , :B8 , .... :B67 ) ...
could you tell me the logic behind even trying to use (it does not work, thankfully) parallel insert with a insert VALUES statement????
a) What is the advantage of using PDML in this statement? Will it be more beneficial if I remove the Parallel Hint?
b) Is it okay to induce usage of indexes as hints? For example, consider the following (please pardon me for the improper formatting):
a) none, it is a single row insert - insert values is - it would make no sense to execute it in parallel.
b) usually not, only if there is a bug - and upon the next patch we would re-evaluate our use of it.
Surprisingly, both execution plans are same and please note that the PLAN ID are also same. Optimizer mode is ALL_ROWS. Table and Index statistics are collected every day using DBMS_STATS
why is that surprising? It just means "optimizer did not need your inputs". The sql ids would be different for these, but since they have the same plan - you would expect the plan hash to be the same (same data = same hash values)
Could you please explain on why the optimizer is choosing the same plan for both the statements?
because your hints happend to coincide with what the optimizer decided to do? I'm not really sure why this is a surprise. We got the same plans - so?
Also, as you have suggested that using hints should be avoided, in this case, what should I do?
Listen to me? Lose the hints.
Rating
(8 ratings)
Is this answer out of date? If it is, please let us know via a Comment