如何优化这个PL / SQL块?

时间:2015-03-19 13:12:59

标签: plsql

我需要更新名为text的表中名为table_to_update的列。字段text是来自另一个名为other_table的表的3个字符串的串联。该脚本按预期工作,但问题是执行需要很长时间(> 20小时),因为表table_to_update中有大约2000万个数据集需要更新。

有什么想法可以改善这个脚本的性能吗?

DECLARE
 v_field1 VARCHAR(20);
 v_field2 VARCHAR(20);
 v_field3 VARCHAR(20);
 v_text VARCHAR(100);


BEGIN
 FOR rec IN (select t_pk from table_to_update where state = 'STATE_1' and text is null order by t_pk desc) -- 20 millions data sets
LOOP

 v_text := null;

  FOR other_record IN (select distinct field1, field1, field3 from other_table where t_fk = rec.t_pk)
  LOOP
    v_field1 := other_record.field1;
    v_field2 := other_record.field2;
    v_field3 := other_record.field3;
    v_text := v_text || v_field2 || ';' || v_field1 || ': '|| v_field3 || ' ';        
  END LOOP;   

update table_to_update set text = v_text where t_pk = rec.t_pk;

END LOOP;

COMMIT;

END;

1 个答案:

答案 0 :(得分:2)

一般来说,优化PL / SQL块的最佳方法是最小化上下文切换的次数(即,从程序代码切换到SQL并返回的频率)。在这种情况下,您可以将此块减少为单个语句(假设您使用的是11g或更高版本):

MERGE INTO table_to_update t2u
USING      (SELECT   t_fk,
                     LISTAGG (field2 || ';' || field1 || ': ' || field3, ' ')
                        WITHIN GROUP (ORDER BY field2)
                        AS agg_field
            FROM     other_table
            GROUP BY t_fk) ot
ON         (ot.t_fk = t2u.t_pk)
WHEN MATCHED THEN
   UPDATE SET
      t2u.text = ot.agg_field
      WHERE      t2u.state = 'STATE_1' AND t2u.text IS NULL
  • LISTAGG是一个聚合函数,用于连接获得的值 来自不同的行。它是在11g中引入的。
  • 您也可以UPDATE执行此操作,但我更喜欢MERGE