2015-03-19 50 views
0

我需要更新名爲table_to_update的表中名爲text的列。字段text是來自另一個表other_table的3個字符串的連接。該腳本按預期工作,但問題是執行(> 20小時)需要很長時間,因爲表table_to_update中需要更新的表中有大約200萬個數據集。如何優化這個PL/SQL塊?

有什麼想法可以改善這個腳本的性能嗎?

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; 
+2

這是否必須是PL/SQL?爲什麼不使用原始SQL和子查詢來處理字符串操作? – mmmmmpie 2015-03-19 13:18:18

+2

@mmmmmpie:內部循環聚合了連接的字符串,因此它看起來不那麼簡單。 – Allan 2015-03-19 13:29:41

+0

正確的是,當您回答時,我正在輸入有關「MERGE」語句的註釋。 :) – mmmmmpie 2015-03-19 13:30:13

回答

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
+0

感謝您提供非常快速的答案。我會嘗試一下,並會很快回復你。 – 2015-03-19 13:40:24