ORA-1652: unable to extend temp segment by 128 in tablespace

系統臨時表空間已經達到64G, 可是依然報ORA-1652錯誤,如今業務申請擴展臨時表空間到128g。算法

  通過抓取AWR報告,發現以下幾條sql語句執行時間最長,通過分析 發現 大部分是 「MINUS 」和「insert into select......」類型語句。重點關注 MINUS。sql

看Top10事件,direct path write temp 出現次數不少,大量等待User I/O,查看執行時間最長的SQL:

7sx6fj2pvrp99函數

INSERT INTO CAMS_ACCT_TEMP03 SELECT * FROM CAMS_ACCT_TEMP01 A WHERE NOT EXISTS(SELECT 1 FROM CAMS_ACCT_TEMP03 B WHERE A.ACCT_NO = B.ACCT_NO) MINUS SELECT * FROM CAMS_ACCT_TEMP02 A WHERE NOT EXISTS(SELECT 1 FROM CAMS_ACCT_TEMP03 B WHERE A.ACCT_NO = B.ACCT_NO)優化

 

  INSERT INTO CAMS_CUST_TEMP03 SELECT * FROM CAMS_CUST_TEMP01 MINUS SELECT * FROM CAMS_CUST_TEMP02;

 

INSERT INTO CAMS_SUB_ACCT_TEMP (COMPANY, OPEN_BANK, ACCT_NO, SUB_ACCT_NO, INTERNAL_KEY) (SELECT COMPANY, OPEN_BANK, ACCT_NO, SUB_ACCT_NO, INTERNAL_KEY FROM    INTF_CAMS_SUB_ACCT WHERE DATA_DATE = :B1 MINUS SELECT COMPANY, OPEN_BANK, ACCT_NO, SUB_ACCT_NO, INTERNAL_KEY FROM INTF_CAMS_SUB_ACCT WHERE DATA_DATE = :B2 );

 

INSERT INTO CAMS_CARD_INFO_TEMP03 SELECT * FROM CAMS_CARD_INFO_TEMP01 MINUS SELECT * FROM CAMS_CARD_INFO_TEMP02;

 

g90k5fb17b34hspa

INSERT INTO CAMS_CUST_TEMP01 (COMPANY , ORG_CODE , CUST_NO , CUST_NAME , CERTI_KIND , CERTI_NO , EFFECTIVE_DATE , ISSUE_ORGAN_REGION , IDENTITY_KIND , COUNTRY , SEX , POST_CODE , ADDRESS , TEL , DATA_STATE , AUDITING_STATE , ERROR_REASON , REPORT_DATE , REPORT_FILE , UPD_USER , UPD_TIME ) SELECT COMPANY , ORG_CODE , CUST_NO , CUST_NAME , CERTI_KIND , CERTI_NO , EFFECTIVE_DATE , ISSUE_ORGAN_REGION , IDENTITY_KIND , COUNTRY , SEX , POST_CODE , ADDRESS , TEL , DATA_STATE , AUDITING_STATE , ERROR_REASON , REPORT_DATE , REPORT_FILE , UPD_USER , UPD_TIME FROM INTF_CAMS_CUST A WHERE A.DATA_DATE = :B13d

首先咱們來了解下 ‘MINUS’函數,minus主要做用在於取兩個 集合/表 補集,就相似對兩個集合排序 而後相似冒泡算法對比去重。code

 

抓了2個sql的執行計劃,能夠發現使用了大量的temp排序,一條sql執行消耗800+MB的temp 排序,能夠經過 not in ,not exists 來改寫,實際工做中,not in比not exists要好。blog

對於須要排序的列,能夠適當創建索引,走索引掃描能夠避免額外排序。排序

SQL1:索引

SQL_ID  cp8cdxcj53rbh, child number 0

-------------------------------------

SELECT * FROM IGRSVISE.CAMS_ACCT_TEMP01 A WHERE NOT EXISTS( SELECT 1 FROM IGRSVISE.CAMS_ACCT_TEMP03 B WHERE A.ACCT_NO = B.ACCT_NO) 

MINUS

SELECT * FROM IGRSVISE.CAMS_ACCT_TEMP02 A WHERE NOT EXISTS( SELECT 1 FROM IGRSVISE.CAMS_ACCT_TEMP03 B WHERE A.ACCT_NO = B.ACCT_NO)

SQL2:

INSERT INTO CAMS_CUST_TEMP03 SELECT * FROM IGRSVISE.CAMS_CUST_TEMP01 MINUS SELECT * FROM IGRSVISE.CAMS_CUST_TEMP02

改寫成以下 not in 

SQL3 :

3;"g90k5fb17b34h";
INSERT INTO CAMS_CUST_TEMP01 (COMPANY ,ORG_CODE ,CUST_NO ,CUST_NAME
,CERTI_KIND ,CERTI_NO ,EFFECTIVE_DATE ,ISSUE_ORGAN_REGION
,IDENTITY_KIND ,COUNTRY ,SEX ,POST_CODE ,ADDRESS ,TEL ,DATA_STATE
,AUDITING_STATE ,ERROR_REASON ,REPORT_DATE ,REPORT_FILE ,UPD_USER
,UPD_TIME ) SELECT COMPANY ,ORG_CODE ,CUST_NO ,CUST_NAME ,CERTI_KIND
,CERTI_NO ,EFFECTIVE_DATE ,ISSUE_ORGAN_REGION ,IDENTITY_KIND ,COUNTRY
,SEX ,POST_CODE ,ADDRESS ,TEL ,DATA_STATE ,AUDITING_STATE ,ERROR_REASON
,REPORT_DATE ,REPORT_FILE ,UPD_USER ,UPD_TIME FROM INTF_CAMS_CUST A
WHERE A.DATA_DATE = :B1

SQL4:

"0d9ua5sqm01jk";
INSERT INTO CAMS_CARD_INFO_TEMP01 (COMPANY, ORG_CODE, CARD_NO,IS_PRIMARY_CARD, MATURITY_DATE, ACCT_MEDIUM, CLOSED_DATE, CARD_STATUS,ERROR_REASON, REPORT_DATE, REPORT_FILE, UPD_USER, UPD_TIME,MAIN_CARD_NO ) 
SELECT COMPANY, ORG_CODE, CARD_NO, IS_PRIMARY_CARD,MATURITY_DATE, ACCT_MEDIUM, CLOSED_DATE, CARD_STATUS, ERROR_REASON,REPORT_DATE, REPORT_FILE, UPD_USER, UPD_TIME, MAIN_CARD_NO FROM INTF_CAMS_CARD_INFO A WHERE A.DATA_DATE = :B1

臨時表還有一種優化方法,相似這種:

with 
cr as 
( 
    select code from product where Name like 'C%' 
)

select * from product where code in (select * from cr)
相關文章
相關標籤/搜索