存储过程更新 table 列花费的时间过多

Stored procedure is taking too much time to update the table columns

我创建了一个存储过程,它花费太多时间来更新 table 的列。假设 3 小时更新 43k 条记录中的 2.5k 条记录。

所以我可以减少更新记录的时间吗?以下是我的逻辑。

procedure UPDATE_MST_INFO_BKC
  (
    P_SAPID IN NVARCHAR2
  )
  as
  v_cityname varchar2(500):='';
  v_neid varchar2(500):='';
  v_latitude varchar2(500):='';
  v_longitude varchar2(500):='';
  v_structuretype varchar2(500):='';
  v_jc_name varchar2(500):='';
  v_jc_code varchar2(500):='';
  v_company_code varchar2(500):='';
  v_cnt number :=0;
  
  begin
  select count(*) into v_cnt from structure_enodeb_mapping where  RJ_SAPID=P_SAPID  and rownum=1;
  
  if v_cnt > 0 then 
  begin
  
   select RJ_CITY_NAME, RJ_NETWORK_ENTITY_ID,LATITUDE,LONGITUDE,RJ_STRUCTURE_TYPE,RJ_JC_NAME,RJ_JC_CODE,'6000' 
   into v_cityname,v_neid,v_latitude, v_longitude, v_structuretype,v_jc_name,v_jc_code,v_company_code from structure_enodeb_mapping where RJ_SAPID=P_SAPID  and rownum=1;

        update tbl_ipcolo_mast_info set 
        
        CITY_NAME                   = v_cityname,
        NEID                        = v_neid,
        FACILITY_LATITUDE           = v_latitude,
        FACILITY_LONGITUDE          = v_longitude,
        RJ_STRUCTURE_TYPE           = v_structuretype,
        RJ_JC_NAME                  = v_jc_name,  
        RJ_JC_CODE                  = v_jc_code,  
        COMPANY_CODE                = v_company_code
        where SAP_ID=P_SAPID;
  
  end;
  end if;   

  end UPDATE_MST_INFO_BKC;

我可以对此做哪些调整?

3 小时?那太过分了。 sap_id 列是否已编入索引?即使不是,43K 行的数据集也太小了。

你怎么称呼那个程序?它是另一个代码的一部分,也许是一些不幸的 loop 逐行执行某些操作(反过来,慢慢地执行)?

一些反对意见:

  • 所有这些变量的数据类型真的是varchar2(500)吗?考虑声明它们,以便它们采用 table 列的数据类型,例如v_cityname structure_enodeb_mapping.rj_city_name%type;。此外,无需明确说明它们的值为 null (:= ''),默认情况下如此
  • select 检查该参数值的 table 中是否有内容的语句应该重写为使用 EXISTS 因为它应该比 rownum = 1 条件下执行得更好用过的。
    • 另外,考虑使用异常处理程序(no-data-found 如果某个 ID 没有行;too-many-rows 如果有两行或更多行)
  • select 将数据收集到变量中的语句具有相同的条件;您真的希望每个 ID 不止一行(作为参数传递)吗?

无论如何,整个过程的代码可以缩短为单个 update 语句:

update tbl_ipcolo_mst_info t set
  (t.city_name, t.neid, ...) = (select s.rj_city_name, 
                                       s.rj_network_entity_id, ...
                                from structure_enodeb_mapping s
                                where s.rj_sapid = t.sap_id
                               )
where t.sap_id = p_sapid;

有什么要更新的,会的。如果没有匹配的t.sap_id,什么也不会发生。

据我了解您的代码,它正在更新 TBL_IPCOLO_MAST_INFO 具有 SAP_ID = P_SAPID 意味着它正在更新一条记录,您必须为每条记录调用该过程。

一次调用该过程并一次性更新所有记录是一个很好的做法。 (在您的情况下,必须仅在一次调用此过程中更新 2.5k 条记录)

根据您的要求,目前,我已将过程代码更新为仅执行 MERGE 语句,这将与您问题中的多个 SQL 相同 P_SAPID.

PROCEDURE UPDATE_MST_INFO_BKC (
    P_SAPID IN   NVARCHAR2
) AS
BEGIN
    MERGE INTO TBL_IPCOLO_MAST_INFO I 
    USING (
            SELECT
                RJ_CITY_NAME,
                RJ_NETWORK_ENTITY_ID,
                LATITUDE,
                LONGITUDE,
                RJ_STRUCTURE_TYPE,
                RJ_JC_NAME,
                RJ_JC_CODE,
                '6000' AS COMPANY_CODE,
                RJ_SAPID
            FROM
                STRUCTURE_ENODEB_MAPPING
            WHERE
                RJ_SAPID = P_SAPID
                AND ROWNUM = 1
            )
    O ON ( I.SAP_ID = O.RJ_SAPID )
    WHEN MATCHED THEN 
    UPDATE SET I.CITY_NAME = O.RJ_CITY_NAME,
                I.NEID = O.RJ_NETWORK_ENTITY_ID,
                I.FACILITY_LATITUDE = O.LATITUDE,
                I.FACILITY_LONGITUDE = O.LONGITUDE,
                I.RJ_STRUCTURE_TYPE = O.RJ_STRUCTURE_TYPE,
                I.RJ_JC_NAME = O.RJ_JC_NAME,
                I.RJ_JC_CODE = O.RJ_JC_CODE,
                I.COMPANY_CODE = O.COMPANY_CODE;

END UPDATE_MST_INFO_BKC;

干杯!!