Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/444.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Plsql 如何优化此PL/SQL块?_Plsql - Fatal编程技术网

Plsql 如何优化此PL/SQL块?

Plsql 如何优化此PL/SQL块?,plsql,Plsql,我需要将名为table\u的表中名为text的列更新为\u update。字段text是另一个名为other\u table的表中3个字符串的浓缩。脚本按预期工作,但问题是执行时间较长(>20小时),因为表表\u to\u update中大约有2000万个数据集需要更新 有什么办法可以改进这个脚本的性能吗 DECLARE v_field1 VARCHAR(20); v_field2 VARCHAR(20); v_field3 VARCHAR(20); v_text VARCHAR(100

我需要将名为
table\u的表中名为
text
的列更新为\u update
。字段
text
是另一个名为
other\u table
的表中3个字符串的浓缩。脚本按预期工作,但问题是执行时间较长(>20小时),因为表
表\u to\u 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;

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

  • LISTAGG
    是一个聚合函数,用于连接获得的值 从不同的行。它是在11g中引入的
  • 您也可以将其作为
    更新
    ,但我更喜欢
    合并

这必须是PL/SQL吗?为什么不直接使用原始SQL和子查询来处理字符串操作?@mmmmm pie:内部循环正在聚合连接的字符串,因此它不像看上去那么简单。对,我在回答时键入了一条关于
MERGE
语句的注释。:)问题是他显然在更新2000万条记录。通过1条更新声明处理所有这些问题,他将看到显著的性能提升。感谢您快速的回答。我会尝试一下,很快会回答你。
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