优化插入语句

时间:2017-03-23 09:50:47

标签: oracle optimization

我有一个插入块,它插入了大约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;
/

1 个答案:

答案 0 :(得分: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的高级提示。您可以轻松地在这样的声明上花费数小时。