2017-03-23 78 views
0

我有一個插入塊,插入幾乎5680969行,需要大約10分鐘執行。我嘗試使用並行提示進行優化,以及諸如彙總查詢等其他內容。這個查詢塊可以進一步優化嗎?任何幫助都感激不盡。優化插入語句

DECLARE 
     vblQueryName VARCHAR2(20); 
    BEGIN 
     vblQueryName:='060_745_085'; 
     INSERT /*+ APPEND */ INTO TABLE_A 
     (
      SOURCE, 
      SN, 
      CLMNUM, 
      CLAIMLINENUMBER, 
      CLMTYPE, 
      CLMTYPEDESC, 
      CLMCATEGORY, 
      MEMID, 
      ENRID, 
      RELFLAG, 
      MEMFIRSTNAME, 
      MEMLASTNAME, 
      GENDER, 
      DOB, 
      ADDR1, 
      ADDR2, 
      CITY, 
      STATE, 
      ZIP, 
      HOMEPHONE, 
      WORKPHONE, 
      LVLID1, 
      LVLDESC1, 
      LVLID2, 
      LVLDESC2, 
      LVLID3, 
      LVLDESC3, 
      LVLID4, 
      LVLDESC4, 
      LVLID5, 
      LVLDESC5, 
      LVLID6, 
      LVLDESC6, 
      LVLID7, 
      LVLDESC7, 
      LVLID8, 
      LVLDESC8, 
      LVLID9, 
      LVLDESC9, 
      LVLID10, 
      LVLDESC10, 
      FROMDATE, 
      TODATE, 
      SERVICEDATE, 
      RCVDATE, 
      PAIDDATE, 
      BILLTYPE, 
      POSCODE, 
      POSDESC, 
      SPECCODE, 
      SPECDESC, 
      DIAGCODE, 
      DIAGDESC, 
      FIRSTDIAGCODE, 
      FIRSTDIAGDESC, 
      SECONDDIAGCODE, 
      SECONDDIAGDESC, 
      THIRDDIAGCODE, 
      THIRDDIAGDESC, 
      FOURTHDIAGCODE, 
      FOURTHDIAGDESC, 
      FIFTHDIAGCODE, 
      FIFTHDIAGDESC, 
      SIXTHDIAGCODE, 
      SIXTHDIAGDESC, 
      SEVENTHDIAGCODE, 
      SEVENTHDIAGDESC, 
      EIGHTHDIAGCODE, 
      EIGHTHDIAGDESC, 
      NINTHDIAGCODE, 
      NINTHDIAGDESC, 
      TENTHDIAGCODE, 
      TENTHDIAGDESC, 
      PROCTYPE, 
      PROCCODE, 
      PROCDESC, 
      REVCODE, 
      DRGCODE, 
      MODIFIERCODE, 
      MODIFIERDESC, 
      CPT4_1, 
      CPT4_2, 
      CPT4_3, 
      HCPCS, 
      CPTII, 
      MODIFIERCODE2, 
      REVCODE1, 
      REVCODE2, 
      REVCODE4, 
      REVCODE3, 
      REVCODE5, 
      ICD9PROCCODE1, 
      ICD9PROCCODE2, 
      ICD9PROCCODE3, 
      ICD9PROCCODE4, 
      ICD9PROCCODE5, 
      ICD9PROCCODE6, 
      DRGTYPE, 
      DRGIDENTIFIER, 
      IPDAYS, 
      DISCHSTATUS, 
      TYPEOFBILL, 
      CLAIMSTATUS, 
      ADJCODE, 
      PROVID, 
      PROVNAME, 
      PROVIDERFIRSTNAME, 
      PROVIDERLASTNAME, 
      PROVNPI, 
      PROVZIPCODE, 
      SERVTYPECODE, 
      SERVTYPEDESC, 
      PROVTYPECODE, 
      PROVTYPEDESC, 
      SERVICECODE, 
      SPECROLLUPCODE, 
      SPECROLLUPDESC, 
      NWKID, 
      NWKNAME, 
      INNWK, 
      NETWORKTYPE, 
      SERVICEUNITS, 
      PAIDAMT, 
      BILLEDAMT, 
      ALLOWEDAMT, 
      PPOSAVINGAMT, 
      ENRPAIDAMT, 
      COINSAMT, 
      COPAYAMT, 
      DEDUCTAMT, 
      NOTALLOWEDAMT, 
      COBAMT, 
      PLANEXCLAMT, 
      LABTESTDATA, 
      SICCODE, 
      SICDESC, 
      SSN, 
      RCVMTH, 
      SRCFILENAME, 
      UDF1, 
      UDFC10, 
      UDFc19, 
      UDFc20, 
      ICDTYPE, 
      VHPAYORID 
     ) 
     SELECT /*+PARALLEL(a,8) */ 
      'SOURCE' AS SOURCE, 
      ROWNUM AS SN, 
      CASE UPPER(a.PROVIDER_NETWORK_PAR_INDICATOR) WHEN 'Y' THEN 'Y_' ELSE 'N_' END || a.CLAIM_NUMBER || a.CLAIM_LINE_NUMBER || ROWNUM AS CLMNUM, 
      a.CLAIM_LINE_NUMBER AS CLAIMLINENUMBER, 
      'MED' AS CLMTYPE, 
      'MEDICAL' AS CLMTYPEDESC , 
      NULL AS CLMCATEGORY, 
      a.MEMID AS MEMID, 
      a.SUBSCRIBER_NUMBER AS ENRID, 
      NULL AS RELFLAG , 
      UPPER(a.MEMBER_FIRST_NAME) AS MEMFIRSTNAME, 
      UPPER(a.MEMBER_LAST_NAME) AS MEMLASTNAME, 
      UPPER(a.MEMBER_GENDER) AS GENDER, 
      a.MEMBER_DATE_OF_BIRTH AS DOB, 
      a.MEMBER_ADDRESS_1 AS ADDR1, 
      a.MEMBER_ADDRESS_2 AS ADDR2, 
      a.MEMBER_CITY AS CITY, 
      a.MEMBER_STATE AS STATE, 
      a.MEMBER_ZIP AS ZIP, 
      a.MEMBER_PHONE AS HOMEPHONE, 
      NULL AS WORKPHONE, 
      'SOURCE' AS LVLID1, 
      'SOURCE' AS LVLDESC1, 
      NULL AS LVLID2, 
      NULL AS LVLDESC2, 
      NVL(lvl.VRSK_EMPLR_GRPID, REGEXP_REPLACE(a.subgroup_number,'[^a-zA-Z0-9]')) AS LVLID3, 
      NVL(lvl.EMPLOYER_GROUP_NM, REGEXP_REPLACE(a.subgroup_number,'[^a-zA-Z0-9]')) AS LVLDESC3, 

      NULL AS LVLID4, 
      NULL AS LVLDESC4, 
      NULL AS LVLID5, 
      NULL AS LVLDESC5, 
      NULL AS LVLID6, 
      NULL AS LVLDESC6, 
      NULL AS LVLID7, 
      NULL AS LVLDESC7, 
      NULL AS LVLID8, 
      NULL AS LVLDESC8, 
      NULL AS LVLID9, 
      NULL AS LVLDESC9, 
      NULL AS LVLID10, 
      NULL AS LVLDESC10, 
      a.SERVICE_START_DATE AS FROMDATE, 
      a.SERVICE_END_DATE AS TODATE, 
      a.SERVICE_START_DATE AS SERVICEDATE, 
      a.CLAIM_RECEIVED_DATE AS RCVDATE, 
      a.CLAIM_PROCESS_DATE AS PAIDDATE, 
      Decode(a.ENCOUNTER_TYPE_CODE, 'FCLTY', 'F', 'PROF', 'P', 'DENT', 'P') AS BILLTYPE, 
      a.PLACE_OF_SERVICE_CODE AS POSCODE, 
      NULL AS POSDESC, 
      e.ROLLUP_SPECCODE AS SPECCODE, 
      e.ROLLUP_SPECDESC AS SPECDESC, 
      COALESCE(a.PRIMARY_DIAGNOSIS_CODE,a.DIAGNOSIS_CODE_2,a.DIAGNOSIS_CODE_3,a.DIAGNOSIS_CODE_4,a.DIAGNOSIS_CODE_5) AS DIAGCODE, 
      NULL AS DIAGDESC, 
      a.PRIMARY_DIAGNOSIS_CODE AS FIRSTDIAGCODE, 
      NULL AS FIRSTDIAGDESC, 
      a.DIAGNOSIS_CODE_2 AS SECONDDIAGCODE, 
      NULL AS SECONDDIAGDESC, 
      a.DIAGNOSIS_CODE_3 AS THIRDDIAGCODE, 
      NULL AS THIRDDIAGDESC, 
      a.DIAGNOSIS_CODE_4 AS FOURTHDIAGCODE, 
      NULL AS FOURTHDIAGDESC, 
      a.DIAGNOSIS_CODE_5 AS FIFTHDIAGCODE, 
      NULL AS FIFTHDIAGDESC, 
      NULL AS SIXTHDIAGCODE, 
      NULL AS SIXTHDIAGDESC, 
      NULL AS SEVENTHDIAGCODE, 
      NULL AS SEVENTHDIAGDESC, 
      NULL AS EIGHTHDIAGCODE, 
      NULL AS EIGHTHDIAGDESC, 
      NULL AS NINTHDIAGCODE, 
      NULL AS NINTHDIAGDESC, 
      NULL AS TENTHDIAGCODE, 
      NULL AS TENTHDIAGDESC, 
      NULL AS PROCTYPE, 
      COALESCE(proc1.PROCCODE, proc2.PROCCODE, proc3.PROCCODE,a.PROCEDURE_CODE, NULLIF('I'||a.ICD_PROCEDURE_CODE_1,'I'), NULLIF('D'||a.AP_DRG,'D')) AS PROCCODE, 
      NULL AS PROCDESC, 
      CASE WHEN proc2.procTypeDesc='Rev Code' THEN proc2.PROCCODE END AS REVCODE, 
      proc3.PROCCODE AS DRGCODE, 
      NULL AS MODIFIERCODE, 
      NULL AS MODIFIERDESC, 
      CASE WHEN proc2.procTypeDesc='CPT4' THEN proc2.PROCCODE END AS CPT4_1, 
      NULL AS CPT4_2, 
      NULL AS CPT4_3, 
      CASE WHEN proc2.procTypeDesc='HCPCS' THEN proc2.PROCCODE END AS HCPCS, 
      NULL AS CPTII, 
      NULL AS MODIFIERCODE2, 
      CASE WHEN proc2.procTypeDesc='Rev Code' THEN proc2.PROCCODE END AS REVCODE1, 
      NULL AS REVCODE2, 
      NULL AS REVCODE4, 
      NULL AS REVCODE3, 
      NULL AS REVCODE5, 
      proc1.PROCCODE AS ICD9PROCCODE1, 
      REPLACE(a.ICD_PROCEDURE_CODE_2, '.') AS ICD9PROCCODE2, 
      REPLACE(a.ICD_PROCEDURE_CODE_3, '.') AS ICD9PROCCODE3, 
      NULL AS ICD9PROCCODE4, 
      NULL AS ICD9PROCCODE5, 
      NULL AS ICD9PROCCODE6, 
      NULL AS DRGTYPE, 
      NULL AS DRGIDENTIFIER, 
      NULL AS IPDAYS, 
      a.DISCHARGE_STATUS_CODE AS DISCHSTATUS, 
      NULL AS TYPEOFBILL, 
      NULL AS CLAIMSTATUS, 
      NULL AS ADJCODE, 
      coalesce(prov.rollupproviderid, a.provider_number) AS PROVID, 
      coalesce(prov.rollupprovidername,a.provider_name) AS PROVNAME, 
      NULL AS PROVIDERFIRSTNAME, 
      NULL AS PROVIDERLASTNAME, 
      NULL AS PROVNPI, 
      SubStr(a.PROVIDER_ZIP, 1, 5) AS PROVZIPCODE, 
      NULL AS SERVTYPECODE, 
      NULL AS SERVTYPEDESC, 
      NULL AS PROVTYPECODE, 
      NULL AS PROVTYPEDESC, 
      NULL AS SERVICECODE, 
      NULL AS SPECROLLUPCODE, 
      NULL AS SPECROLLUPDESC, 
      NVL(d.ROLLUPNWKID,a.PROVIDER_REGION_CODE) AS NWKID, 
      COALESCE(d.ROLLUPNWKNAME,a.PROVIDER_REGION_CODE) AS NWKNAME, 
      CASE UPPER(a.PROVIDER_NETWORK_PAR_INDICATOR) WHEN 'Y' THEN 'Y' ELSE 'N' END AS INNWK, 
      NULL AS NETWORKTYPE, 
      a.SERVICE_UNIT_COUNT AS SERVICEUNITS, 
      Nvl(a.PAID_AMOUNT,0) AS PAIDAMT, 
      Nvl(a.CHARGED_AMOUNT,0) AS BILLEDAMT, 
      Nvl(a.CHARGED_AMOUNT *0.54,0) AS ALLOWEDAMT, 
      NULL AS PPOSAVINGAMT, 
      NVL(a.COPAY_AMOUNT,0) + NVL(a.COINSURANCE_AMOUNT,0) + NVL(a.DEDUCTIBLE_AMOUNT,0) AS ENRPAIDAMT, -- corrected on /5/30/2013 
      Nvl(a.COINSURANCE_AMOUNT,0) AS COINSAMT, 
      Nvl(a.COPAY_AMOUNT,0) AS COPAYAMT, 
      Nvl(a.DEDUCTIBLE_AMOUNT,0) AS DEDUCTAMT, 
      Nvl(a.NOT_COVERED_AMOUNT,0) AS NOTALLOWEDAMT, 
      Nvl(a.COB_AMOUNT,0) AS COBAMT, 
      NULL AS PLANEXCLAMT, 
      NULL AS LABTESTDATA, 
      NULL AS SICCODE, 
      NULL AS SICDESC, 
      NULL AS SSN, 
      a.RECEIVEDMONTH AS RCVMTH, 
      a.SOURCEFILENAME AS SRCFILENAME, 
      'BCBSNC' AS UDF1 , 
      a.SUBSCRIBER_NUMBER|| TO_CHAR(a.MEMBER_DATE_OF_BIRTH,'YYYYMMDD') AS UDFC10,--ICE176721 
      a.subgroup_number AS UDFc19, 
      a.benefit_package_id AS UDFc20, 
      CASE WHEN a.SERVICE_START_DATE>=to_date('20151001','YYYYMMDD') THEN 'ICD10' else 'ICD9' end as ICDTYPE, 
      payor.PAYORID AS VHPAYORID 
     FROM 
      HI0000001.HI_CLAIMS_SOURCE a 
     LEFT JOIN 
      HR_745_LOA_SOURCE lvl 
     ON 
      a.SUBGROUP_NUMBER = lvl.SUBGROUP_ID 
     LEFT JOIN 
      HR_745_NWK_CIGNA d 
     ON 
      a.PROVIDER_REGION_CODE = d.NWKID 
     AND 
      d.SOURCE = 'SOURCE' 
     LEFT JOIN 
      HR_745_SPEC_MERGED e 
     ON 
      a.PROVIDER_SPECIALTY_CODE = e.SRC_SPECCODE 
     AND 
      e.PAYER='BCBSNC' 
     LEFT JOIN 
      zzz_procs proc1 
     ON 
      'I'||REPLACE(a.ICD_PROCEDURE_CODE_1,'.') = proc1.proccode 
     LEFT JOIN 
      zzz_procs proc2 
     ON 
      CASE WHEN LENGTH(a.PROCEDURE_CODE)=4 AND SUBSTR(a.PROCEDURE_CODE,1,1)='0' THEN 'R'||SUBSTR(a.PROCEDURE_CODE,-3) ELSE a.PROCEDURE_CODE END = proc2.PROCCODE 
     LEFT JOIN 
      zzz_procs proc3 
     ON 
      'D'|| a.AP_DRG = proc3.proccode 
     LEFT JOIN 
      HR_GLOBAL_PAYORLIST payor 
     ON 
      payor.TABLENAME = 'HI_CLAIMS_BCBSNC' 
     LEFT JOIN 
      HR_745_PROVIDER prov 
     ON 
      'SOURCE' = prov.SOURCE 
     AND 
      UPPER(COALESCE(a.provider_number,'NULL')) = prov.provid 
     AND 
      UPPER(Nvl(a.provider_name, 'NULL')) = prov.provname 
     WHERE 
      a.ENCOUNTER_SERVICE_TYPE_CODE NOT IN ('06','02') AND a.ENCOUNTER_TYPE_CODE <>'CP' 
     AND 
      REGEXP_REPLACE(a.subgroup_number,'[^a-zA-Z0-9]') IS NOT NULL 
     AND 
      NVL(lvl.VRSK_EMPLR_GRPID, a.subgroup_number) NOT IN 
      (SELECT drp.lvl3id FROM hr_745_lvl3_drop drp WHERE source='BCBSNC') 
     AND 
     (NVL(lvl.VRSK_EMPLR_GRPID, a.subgroup_number)<>'539431' OR a.CLAIM_PROCESS_DATE<LAST_DAY(TO_DATE('2016-09','yyyy-mm'))); 

     COMMIT; 
     DBMS_OUTPUT.PUT_LINE('Query Executed: ' || vblqueryName); 
     INSERT INTO VH_QUERYLOG(QueryName,CURTIME) VALUES(vblQueryName,SYSDATE); 
     EXCEPTION WHEN NO_DATA_FOUND THEN NULL; 
    END; 
/
+0

你在桌上有多少個索引?桌子上有觸發器嗎? –

+0

@RaduGheorghiu:我沒有任何索引或觸發器在這張桌子上。 –

+1

首先檢查是插入緩慢還是查詢。它自己的SELECT語句花了多長時間?聲明的執行計劃是什麼? –

回答

1

INSERT之前添加以下語句:

execute immediate 'alter session enable parallel dml'; 

刪除所有的提示,只在頂部使用一個提示:

/*+ APPEND PARALLEL */ 

這使得整個語句來運行並行,而不僅僅是SELECT的某些部分。除非您使用的是舊的,不受支持的Oracle版本,否則通常希望避免在並行提示中列出對象。根據系統設置的方式,使用沒有數字的並行提示有望選擇更好的並行性。如果這不起作用,那麼我建議嘗試不同的數字。 (簡而言之,更高的DOP總是更快,但收益遞減,並且可以從其他語句中竊取資源。)

完成此操作後,請查看INSERT的解釋計劃。確保它使用的是LOAD AS SELECT而不是CONVENTIONAL INSERT - 這就是您如何判斷語句是使用直接路徑寫入。 APPEND提示是棘手的,有很多事情可能會阻止它正常工作。

然後運行代碼並生成如下所示的SQL Monitor報告:select dbms_sqltune.report_sql_monitor(sql_id => 'the insert SQL_ID') from dual;。該報告將告訴你查詢中的哪個操作很慢,如果有的話。解釋計劃可能會生成幾十行,如果沒有SQL Monitor報告,您將不得不猜測哪部分緩慢。某些連接條件看起來很複雜,如果您看到一些操作,其中估計的行數是1但實際更高,導致NESTED LOOP而不是HASH JOIN,我不會感到驚訝。

這些是平行入門的高級提示INSERT。您可以輕鬆地在這樣的陳述上花費數小時。