某CRM數據庫系統跑批一條SQL執行了24小時 還沒執行完
問題SQL已經定位到,SQL中表信息以及執行計劃如下:
SELECT t.CRM_DT,
......
......
SUM(nvl(t.OUTSTD_AMT, 0) * T9.HL) AS amt,
T7.CB_HOST_NO as CB_CUST_ID
from A_O_DDD_CCCC_FFF_EEEE_DDD_TEMP t
inner JOIN C_S_EE_TTT_FFF@db_link_XXXX T5------------
ON t.FAC_ID = T5.ID
inner JOIN C_S_EE_TTTL_CCC_FFFF_CIF@db_link_XXXX T6
ON T5.CDT_FILE_ID = T6.CDT_FILE_ID
inner JOIN C_S_EE_TTT_CCC@db_link_XXXX T7------------
ON T7.ID = T6.CIF_ID
AND T7.MT_CIF_TYP_CD = 'CRM_MT_CIF_TYP_CD_14'
LEFT JOIN C_S_CC_BBBB@db_link_XXXX T9
on T9.yb = T.MT_CUR_CD
and T9.STARTDATE <= TO_DATE('20180525', 'YYYYMMDD') --開
and T9.ENDDATE > TO_DATE('20180525', 'YYYYMMDD') --閉
LEFT JOIN C_S_EE_TTT_MM_BB@db_link_XXXX T10
ON T.MT_BR_CD = T10.cd
WHERE T6.MT_FAC_REL_CD = 'CRM_MT_FAC_REL_CD_04'
and T7.MT_CIF_TYP_CD = 'CRM_MT_CIF_TYP_CD_14'
GROUP BY t.crm_dt,t.open_branch_no, t7.no,t7.CB_HOST_NO,T10.IS_SME,T7.NM;
---查詢表信息如下---
select count(1) from A_O_DDD_CCCC_FFF_EEEE_DDD_TEMP t;--709930
select count(1) from C_S_EE_TTT_FFF@db_link_XXXX t;--1614490
select count(1) from C_S_EE_TTTL_CCC_FFFF_CIF@db_link_XXXX;--1114978
select count(1) from C_S_EE_TTT_CCC@db_link_XXXX;--609038
select count(1) from C_S_CC_BBBB@db_link_XXXX;--1459
select count(1) from C_S_EE_TTT_MM_BB@db_link_XXXX;--3313
----------重新收集相關表的統計信息,跑了3個小時還是沒出結果,執行計劃如下-----------
Plan hash value: 3812144039
------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |IN-OUT|
------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2183 | 8375 (2)| 00:01:41 | | |
| 1 | HASH GROUP BY | | 1 | 2183 | 8375 (2)| 00:01:41 | | |
| 2 | NESTED LOOPS OUTER | | 1 | 2183 | 8374 (2)| 00:01:41 | | |
| 3 | VIEW | | 1 | 2095 | 8373 (2)| 00:01:41 | | |
|* 4 | HASH JOIN OUTER | | 1 | 2246 | 8373 (2)| 00:01:41 | | |
| 5 | VIEW | | 1 | 2208 | 8369 (2)| 00:01:41 | | |
|* 6 | HASH JOIN | | 1 | 807 | 8369 (2)| 00:01:41 | | |
| 7 | NESTED LOOPS | | 1 | 746 | 6611 (2)| 00:01:20 | | |
| 8 | MERGE JOIN CARTESIAN| | 1 | 591 | 6610 (2)| 00:01:20 | | |
| 9 | REMOTE | C_S_EE_TTT_FFF | 1 | 204 | 2 (0)| 00:00:01 | DB_LI~ | R->S |
| 10 | BUFFER SORT | | 304K| 112M| 6608 (2)| 00:01:20 | | |
| 11 | REMOTE | C_S_EE_TTT_CCC | 304K| 112M| 6608 (2)| 00:01:20 | DB_LI~ | R->S |
| 12 | REMOTE | C_S_EE_TTTL_CCC_FFFF_CIF | 1 | 155 | 1 (0)| 00:00:01 | DB_LI~ | R->S |
| 13 | TABLE ACCESS FULL | A_O_DDD_CCCC_FFF_EEEE_DDD_TEMP | 709K| 41M| 1753 (1)| 00:00:22 | | |
| 14 | REMOTE | C_S_CC_BBBB | 11 | 418 | 4 (0)| 00:00:01 | DB_LI~ | R->S |
| 15 | REMOTE | C_S_EE_TTT_MM_BB | 1 | 88 | 1 (0)| 00:00:01 | DB_LI~ | R->S |
------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T9"."YB"(+)="T"."MT_CUR_CD")
6 - access("T"."FAC_ID"="T5"."ID")
Remote SQL Information (identified by operation id):
----------------------------------------------------
9 - SELECT "ID","CDT_FILE_ID" FROM "C_S_EE_TTT_FFF" "T5" (accessing 'DB_LINK_CCRM' )
11 - SELECT "ID","NO","MT_CIF_TYP_CD","NM","CB_HOST_NO" FROM "C_S_EE_TTT_CCC" "T7" WHERE
"MT_CIF_TYP_CD"='CRM_MT_CIF_TYP_CD_14' (accessing 'DB_LINK_CCRM' )
12 - SELECT "CDT_FILE_ID","CIF_ID","MT_FAC_REL_CD" FROM "C_S_EE_TTTL_CCC_FFFF_CIF" "T6" WHERE
"MT_FAC_REL_CD"='CRM_MT_FAC_REL_CD_04' AND :1="CIF_ID" AND :2="CDT_FILE_ID" (accessing 'DB_LINK_CCRM' )
14 - SELECT "STARTDATE","ENDDATE","YB","HL" FROM "C_S_CC_BBBB" "T9" WHERE "ENDDATE">TO_DATE(' 2018-05-25 00:00:00',
'syyyy-mm-dd hh24:mi:ss') AND "STARTDATE"<=TO_DATE(' 2018-05-25 00:00:00', 'syyyy-mm-dd hh24:mi:ss') (accessing
'DB_LINK_CCRM' )
15 - SELECT "CD","IS_SME" FROM "C_S_EE_TTT_MM_BB" "T10" WHERE :1="CD" (accessing 'DB_LINK_CCRM' )
由上面執行計劃可知ID=8發生了笛卡爾積
什麼情況下會發生笛卡爾積
1)表與表之間沒有直接關聯條件
2)表統計信息過期導致優化器估算返回的結果集爲1
ID=8的兒子節點有兩個分別是9和10 ID=9優化器估算C_S_EE_TTT_FFF全表掃描返回的結果集是rows=1行。
這個SQL ID=9這一步最先執行,由於rows算錯爲1,導致後面的rows全部都跟着錯變爲1
其實這個表返回1614490行 ID=11的C_S_EB_TBL_CIF表返回1114978行,
他們笛卡爾積的結果是1614490*1114978=1800120831220,會產生1.8萬億行中間結果集。所以跑不出結果很正常。
ID=9的Operation是REMOTE,所以這是一個dblink。剛剛開發人員收集統計信息只能收集本機,對遠端數據庫卻束手無策
所以這裏只需要一個hint /*+ CARDINALITY(T5 1000000) */ 讓優化器認爲T5返回的結果集是1000000行,搞定!!!
優化後的執行計劃如下:
Plan hash value: 1122908073
-----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Inst |IN-OUT|
-----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 965K| 2010M| | 503K (1)| 01:40:45 | | |
| 1 | HASH GROUP BY | | 965K| 2010M| 2514M| 503K (1)| 01:40:45 | | |
|* 2 | HASH JOIN RIGHT OUTER | | 965K| 2010M| | 63645 (1)| 00:12:44 | | |
| 3 | REMOTE | C_S_EE_TTT_MM_BB | 3313 | 284K| | 23 (0)| 00:00:01 | DB_LI~ | R->S |
| 4 | VIEW | | 965K| 1929M| | 63616 (1)| 00:12:44 | | |
|* 5 | HASH JOIN RIGHT OUTER| | 965K| 2068M| | 63616 (1)| 00:12:44 | | |
| 6 | REMOTE | C_S_CC_BBBB | 11 | 418 | | 4 (0)| 00:00:01 | DB_LI~ | R->S |
| 7 | VIEW | | 886K| 1867M| | 63606 (1)| 00:12:44 | | |
|* 8 | HASH JOIN | | 886K| 682M| 49M| 63606 (1)| 00:12:44 | | |
| 9 | TABLE ACCESS FULL | A_O_DDD_AAAA_FFF_EEEE_DDD_TEMP | 709K| 41M| | 1753 (1)| 00:00:22 | | |
|* 10 | HASH JOIN | | 559K| 398M| 161M| 39328 (1)| 00:07:52 | | |
| 11 | REMOTE | | 304K| 112M| | 6608 (2)| 00:01:20 | DB_LI~ | R->S |
| 12 | REMOTE | C_S_EE_TTT_FFF | 1000K| 194M| | 2 (0)| 00:00:01 | DB_LI~ | R->S |
-----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."MT_BR_CD"="T10"."CD"(+))
5 - access("T9"."YB"(+)="T"."MT_CUR_CD")
8 - access("T"."FAC_ID"="T5"."ID")
10 - access("T5"."CDT_FILE_ID"="T6"."CDT_FILE_ID")
Remote SQL Information (identified by operation id):
----------------------------------------------------
3 - SELECT /*+ */ "CD","IS_SME" FROM "C_S_EE_TTT_MM_BB" "T10" (accessing 'DB_LINK_CCRM' )
6 - SELECT /*+ */ "STARTDATE","ENDDATE","YB","HL" FROM "C_S_CC_BBBB" "T9" WHERE "ENDDATE">TO_DATE(' 2018-05-25
00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "STARTDATE"<=TO_DATE(' 2018-05-25 00:00:00', 'syyyy-mm-dd hh24:mi:ss') (accessing
'DB_LINK_CCRM' )
11 - SELECT "A1"."ID","A1"."NO","A1"."MT_CIF_TYP_CD","A1"."NM","A1"."CB_HOST_NO","A2"."CDT_FILE_ID","A2"."CIF_ID","A2"."M
T_FAC_REL_CD" FROM "C_S_EB_TBL_CIF" "A1","C_S_EB_TBL_CDT_FILE_CIF" "A2" WHERE "A2"."MT_FAC_REL_CD"='CRM_MT_FAC_REL_CD_04'
AND "A1"."ID"="A2"."CIF_ID" AND "A1"."MT_CIF_TYP_CD"='CRM_MT_CIF_TYP_CD_14' (accessing 'DB_LINK_CCRM' )
12 - SELECT /*+ OPT_ESTIMATE (TABLE "T5" ROWS=1000000.000000 ) */ "ID","CDT_FILE_ID" FROM "C_S_EE_TTT_FFF" "T5"
(accessing 'DB_LINK_CCRM' )
可以看出ID=12 Rows爲1000k 執行計劃恢復正常,笛卡爾積消失。SQL用了僅僅50秒就出結果