PLSQL过程需要很长时间才能执行

时间:2018-03-22 08:24:44

标签: oracle stored-procedures plsql

我创建了下面的程序,在添加粗体代码之前运行得很好。现在它一次插入100条记录。已经超过一个小时,它只插入了4000条记录。有200万条记录要插入。有什么方法可以加快处决吗?

create or replace PROCEDURE LOAD_ADDRESS_PROCEDURE AS 

CNTY varchar2(100);

ST varchar2(100); 

createdby_value varchar2(50);

**defaultAddress_value varchar2(1);**

CURSOR C1 is 

SELECT ADDRESS, CITY, STATE, ZIP, COUNTRY, seasonal_start_day, seasonal_start_month, seasonal_end_day, seasonal_end_month, key_address_id, key_account_id, BAD_ADDRESS,
CREATED, CREATED_BY, address_type,

(select siebel_country_name from STATE_AND_COUNTRY_VALUES_LIST where s.COUNTRY IS NULL and s.state = siebel_state_abbreviation) newCNTY,

(select SF_COUNTRY_ABBREVIATION FROM STAGE_COUNTRY WHERE SIEBEL_COUNTRY = s.Country) newCountry,

(select SF_COUNTRY_ABBREVIATION FROM STAGE_COUNTRY 
WHERE SIEBEL_COUNTRY = (select siebel_country_name from STATE_AND_COUNTRY_VALUES_LIST where s.COUNTRY IS NULL and s.state = siebel_state_abbreviation)) newCountry1,

(SELECT SIEBEL_LOGIN from STAGE_USER where KEY_USER_ID = s.CREATED_BY) SiebelLogin,

(SELECT SALESFORCE_USER from STAGE_USER where KEY_USER_ID = s.CREATED_BY) SFUSER,

(SELECT KEY_USER_ID from STAGE_USER where KEY_USER_ID = s.CREATED_BY) KeyUserID,

**(SELECT KEY_PRIMARY_ADDRESS_ID FROM STAGE_ACCOUNT WHERE KEY_PRIMARY_ADDRESS_ID = s.KEY_ADDRESS_ID) defaultAddress**

FROM STAGE_ADDRESS s;

BEGIN

FOR i IN C1 LOOP

ST := i.state;

CNTY := i.country;

/*if(i.newCountry = i.newCNTY) then*/

/*if (i.country  is null) then

CNTY := i.newCountry1;

end if;

comment end*/

if (i.state = 'NA') then

ST := NULL;

end if;

/*end if;*/

/*

if(CNTY != i.newCountry) then

CNTY := i.newCountry;

end if;

if(i.newCountry is null) then

CNTY := NULL;

end if;

comment end*/

IF(CNTY IS NULL) THEN
    CNTY := i.newCountry1;
    ELSE
    CNTY := i.newCountry;
END IF;

IF(i.CREATED_BY = i.KeyUserID AND i.SFUSER = 'MIGRATIONUSER') THEN
createdby_value := 'MIGRATIONUSER';
ELSE
createdby_value := i.KeyUserID;
END IF;

**IF(i.defaultAddress IS NOT NULL) THEN
defaultAddress_value := 'Y';
ELSE
defaultAddress_value := 'N';
END IF;**

INSERT INTO LOAD_ADDRESS(NPSP__MAILINGSTREET__C, NPSP__MAILINGCITY__C, NPSP__MAILINGSTATE__C, NPSP__MAILINGPOSTALCODE__C, NPSP__MAILINGCOUNTRY__C, NPSP__SEASONAL_START_DAY__C,
NPSP__SEASONAL_START_MONTH__C, NPSP__SEASONAL_END_DAY__C, NPSP__SEASONAL_END_MONTH__C, ERP_EXTERNAL_ID_C, NPSP__HOUSEHOLD_ACCOUNT__C, ADDRESS_STATUS_OVERRIDE, CREATED, 
CREATED_BY, NPSP_ADDRESS_TYPE_C, **NPSP__DEFAULT_ADDRESS__C**) VALUES 
(i.ADDRESS, REGEXP_REPLACE(i.CITY, '|||||', ' '), ST, i.ZIP, CNTY, i.seasonal_start_day, i.seasonal_start_month, i.seasonal_end_day, i.seasonal_end_month, i.key_address_id, i.key_account_id, 
DECODE(i.BAD_ADDRESS,'Y','1','N','0'), i.CREATED, createdby_value, i.address_type, **defaultAddress_value**);

COMMIT;

END LOOP;

END LOAD_ADDRESS_PROCEDURE;

2 个答案:

答案 0 :(得分:3)

您可以重写您的过程以在单个insert语句中执行所有逻辑,例如:

INSERT INTO load_address
  (npsp__mailingstreet__c,
   npsp__mailingcity__c,
   npsp__mailingstate__c,
   npsp__mailingpostalcode__c,
   npsp__mailingcountry__c,
   npsp__seasonal_start_day__c,
   npsp__seasonal_start_month__c,
   npsp__seasonal_end_day__c,
   npsp__seasonal_end_month__c,
   erp_external_id_c,
   npsp__household_account__c,
   address_status_override,
   created,
   created_by,
   npsp_address_type_c,
   npsp__default_address__c)
  SELECT address,
         regexp_replace(i.city, '|||||', ' '),
         CASE
           WHEN state = 'NA' THEN
            NULL
           ELSE
             state
         END state,
         zip,
         CASE
           WHEN country IS NULL THEN
            newcountry1
           ELSE
            newcountry
         END country,
         seasonal_start_day,
         seasonal_start_month,
         seasonal_end_day,
         seasonal_end_month,
         key_address_id,
         key_account_id,
         DECODE(bad_address, 'Y', '1', 'N', '0'),
         created,
         CASE
           WHEN created_by = keyuserid
                AND sfuser = 'MIGRATIONUSER' THEN
            sfuser
           ELSE
            keyuserid
         END createdby_value,
         address_type,
         CASE
           WHEN default_address IS NOT NULL THEN
            'Y'
           ELSE
            'N'
         END defaultaddress_value
  FROM   (SELECT address,
                 city,
                 state,
                 zip,
                 country,
                 seasonal_start_day,
                 seasonal_start_month,
                 seasonal_end_day,
                 seasonal_end_month,
                 key_address_id,
                 key_account_id,
                 bad_address,
                 created,
                 created_by,
                 address_type,

                 (SELECT siebel_country_name
                  FROM   state_and_country_values_list
                  WHERE  s.country IS NULL
                  AND    s.state = siebel_state_abbreviation) newcnty,

                 (SELECT sf_country_abbreviation
                  FROM   stage_country
                  WHERE  siebel_country = s.country) newcountry,

                 (SELECT sf_country_abbreviation
                  FROM   stage_country
                  WHERE  siebel_country = (SELECT siebel_country_name
                                           FROM   state_and_country_values_list
                                           WHERE  s.country IS NULL
                                           AND    s.state = siebel_state_abbreviation)) newcountry1,

                 su.siebel_login siebellogin,
                 su.salesforce_user sfuser,
                 su.key_user_id keyuserid,

                 (SELECT key_primary_address_id
                  FROM   stage_account
                  WHERE  key_primary_address_id = s.key_address_id) defaultaddress
          FROM   stage_address s
                 LEFT OUTER JOIN stage_user su ON s.created_by = su.key_user_id);

我已将status_user上的标量子查询移动到外连接,因为连接可能比查询同一个表3次更有效。你可能可以用其他标量子查询做类似的事情(即将它们组合成几个连接或者其他东西)但是我已经把它留给你玩了。

答案 1 :(得分:0)

我建议你完全重写SELECT。您应该使用加入与STAGE_USER,STAGE_COUNTRY以及查询使用的任何其他表。

有一些IF可以(至少,我希望如此)通过使用CASE(或DECODE)重写,这样可以使用 fast SQL(直接INSERT INTO)代替 PL / SQL(在循环中)。

顺便说一句,你在循环中提交 - 删除外面的COMMIT。