原SQL:业务需求需要开发一张表,但是发现执行很慢,我就看了执行计划,
MERGE JOIN CARTESIAN发生笛卡尔积,4dp这张表和6cp这张表发生笛卡尔积,生成的结果集3和8mp又发生一次结果集,也就是说
本身没有关系的表发生了笛卡尔积。这里需要声明几点,cp这张表数据将近50万,mp有将近80万的数据,dp也就不到10条数据
mt表有150万数据量
select
null BAIHUI_ID,
TRANSQ,
DETLSQ,
ACCTNO,
mp.member_cd CUSTAC,
TRANDT TRASDT,
TRANAM,
TRANTM TRASTM,
avalbl AVALBL,
SERVTP CHNLNO,
dp.name CNOVAL,
decode(AMNTCD, 'C', '转入', 'D', '转出') FLOWTP,
INTRCD,
class1,
TRANST,
decode(mt.transt,'1','成功','0','失败')TRTVAL,
greatest(sysdate) UPDATETIME,
cp.CUSTAC MEBECD,
MERCNO
from ods_member_trans mt
inner join dim_client_tp dp
on (mt.servtp = dp.id)
inner join ods_member_mapping mp
on(mt.member_cd=mp.mapping_cd)
inner join ods_custac_mapping cp
on(cp.mapping_cd=mt.custac);
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------
Plan hash value: 4130571362
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 378 | 13937 (1)| 00:02:48 |
|* 1 | HASH JOIN | | 1 | 378 | 13937 (1)| 00:02:48 |
| 2 | MERGE JOIN CARTESIAN | | 363 | 76593 | 2603 (1)| 00:00:32 |
| 3 | MERGE JOIN CARTESIAN| | 1 | 158 | 892 (1)| 00:00:11 |
| 4 | TABLE ACCESS FULL | DIM_CLIENT_TP | 1 | 114 | 2 (0)| 00:00:01 |
| 5 | BUFFER SORT | | 468K| 19M| 890 (1)| 00:00:11 |
| 6 | TABLE ACCESS FULL | ODS_CUSTAC_MAPPING | 468K| 19M| 890 (1)| 00:00:11 |
| 7 | BUFFER SORT | | 774K| 39M| 1713 (1)| 00:00:21 |
| 8 | TABLE ACCESS FULL | ODS_MEMBER_MAPPING | 774K| 39M| 1711 (1)| 00:00:21 |
| 9 | TABLE ACCESS FULL | ODS_MEMBER_TRANS | 1487K| 236M| 11330 (1)| 00:02:16 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("CP"."MAPPING_CD"="MT"."CUSTAC" AND "MT"."MEMBER_CD"="MP"."MAPPING_CD"
AND "MT"."SERVTP"="DP"."ID")
已选择22行。
我使用了hint关闭这个笛卡尔积以后,发现还是很慢查看执行计划, 走了NL,执行计划如下
SQL>
SQL> explain plan for
2 select /*+ OPT_PARAM('_optimizer_mjc_enabled','false') */null BAIHUI_ID,
3 TRANSQ,
4 DETLSQ,
5 ACCTNO,
6 mp.member_cd CUSTAC,
7 TRANDT TRASDT,
8 TRANAM,
9 TRANTM TRASTM,
10 avalbl AVALBL,
11 SERVTP CHNLNO,
12 dp.name CNOVAL,
13 decode(AMNTCD, 'C', '转入', 'D', '转出') FLOWTP,
14 INTRCD,
15 class1,
16 TRANST,
17 decode(mt.transt,'1','成功','0','失败')TRTVAL,
18 greatest(sysdate) UPDATETIME,
19 cp.CUSTAC MEBECD,
20 MERCNO
21 from ods_member_trans mt
22 inner join dim_client_tp dp
23 on (mt.servtp = dp.id)
24 inner join ods_member_mapping mp
25 on(mt.member_cd=mp.mapping_cd)
26 inner join ods_custac_mapping cp
27 on(cp.mapping_cd=mt.custac);
已解释。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
Plan hash value: 3453093643
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 378 | 13937 (1)| 00:02:48 |
|* 1 | HASH JOIN | | 1 | 378 | 13937 (1)| 00:02:48 |
| 2 | NESTED LOOPS | | 363 | 76593 | 2603 (1)| 00:00:32 |
| 3 | NESTED LOOPS | | 1 | 158 | 892 (1)| 00:00:11 |
| 4 | TABLE ACCESS FULL| DIM_CLIENT_TP | 1 | 114 | 2 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL| ODS_CUSTAC_MAPPING | 468K| 19M| 890 (1)| 00:00:11 |
| 6 | TABLE ACCESS FULL | ODS_MEMBER_MAPPING | 774K| 39M| 1711 (1)| 00:00:21 |
| 7 | TABLE ACCESS FULL | ODS_MEMBER_TRANS | 1487K| 236M| 11330 (1)| 00:02:16 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("CP"."MAPPING_CD"="MT"."CUSTAC" AND
"MT"."MEMBER_CD"="MP"."MAPPING_CD" AND "MT"."SERVTP"="DP"."ID")
已选择20行。
最后我使用了HASH和NL的hint来进行优化,由于dp这张表就不到10条数据,所以选择NL的方式,最后12秒数据就执行出来了
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
Plan hash value: 2582556817
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 378 | 13936 (1)| 00:02:48 |
|* 1 | HASH JOIN | | 1 | 378 | 13936 (1)| 00:02:48 |
|* 2 | HASH JOIN | | 1 | 325 | 12223 (1)| 00:02:27 |
| 3 | NESTED LOOPS | | 1 | 281 | 11332 (1)| 00:02:16 |
| 4 | TABLE ACCESS FULL| DIM_CLIENT_TP | 1 | 114 | 2 (0)| 00:00:01 |
|* 5 | TABLE ACCESS FULL| ODS_MEMBER_TRANS | 1 | 167 | 11330 (1)| 00:02:16 |
| 6 | TABLE ACCESS FULL | ODS_CUSTAC_MAPPING | 468K| 19M| 890 (1)| 00:00:11 |
| 7 | TABLE ACCESS FULL | ODS_MEMBER_MAPPING | 774K| 39M| 1711 (1)| 00:00:21 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("MT"."MEMBER_CD"="MP"."MAPPING_CD")
2 - access("CP"."MAPPING_CD"="MT"."CUSTAC")
5 - filter("MT"."SERVTP"="DP"."ID")
已选择21行。