2012-02-06 21 views
2

我一直在努力提高存储过程的性能,并且由于必须运行四个非常类似的更新而出现了很大的减速。如何在Oracle中组合多个更新语句?

我在MySql中发现了类似麻烦的信息,这有帮助,但我无法实现我学到的东西,也许Oracle的运行方式不同。

我尝试过的东西包括:通过合并批量插入,创建辅助temp_table和根本没有临时表,但没有任何改进。

作为Oracle的新手,完全有可能我只是以错误的方式去做。

任何建议或答案或指导的答案将大大apreciated,因为我已经用尽了想法,现在只用蛮力和无知工作。

UPDATE TEMP_TABLE TI SET T.ItemPrice_One = 
     (
     SELECT ItemPrice 
     FROM Temp.View_Items V 
     WHERE V.Item_Name     =   'Item_Name_One' 
     AND V.ID       =   T.ID 
     AND V.Date       =   T.Date 
     ); 

UPDATE TEMP_TABLE TI SET T.ItemPrice_Two = 
     (
     SELECT ItemPrice 
     FROM Temp.View_Items V 
     WHERE V.Item_Name     =   'Item_Name_Two' 
     AND V.ID       =   T.ID 
     AND V.Date       =   T.Date 
     ); 

UPDATE TEMP_TABLE TI SET T.ItemPrice_Three = 
     (
     SELECT ItemPrice 
     FROM Temp.View_Items V 
     WHERE V.Item_Name     =   'Item_Name_Three' 
     AND V.ID       =   T.ID 
     AND V.Date       =   T.Date 
     ); 
+1

你真的想更新每个UPDATE语句的每一行TEMP_TABLE吗? (因为这是你的每一个更新将做什么)。我有点困惑,你想更新的主表是什么? – tbone 2012-02-06 19:08:06

+0

您可以将这三个更新轻松地组合到一个更新中。这是个问题吗? – 2012-02-06 19:21:10

+0

谢谢大家闪电般的快速回应。我会尽力澄清它的目的。 Temp_Table通常很小,可以从2行到200之间的任何地方。如果ID和日期与更大的视图相匹配,那么该行中的相应列将被更新。 – dee 2012-02-06 19:38:29

回答

2

什么你正在试图做的本质上是一个旋转的操作 - 打开多个行值分成多个列的值在一行中。下面是在Oracle中使用常用技术进行数据透视查询的一种方法(未经测试,但我认为它应该按原样)。从版本11g开始,就有一个内置的PIVOT操作,但我还没有真正看过它 - 它可能是一种更直接的方法来执行您所需要的操作。

UPDATE TEMP_TABLE TI SET (T.ItemPrice_One, T.ItemPrice_Two,T.ItemPrice_Three) = 
    (
    SELECT 
     MAX(CASE WHEN V.Item_Name='Item_Name_One' THEN ItemPrice ELSE NULL END) Item_Price_One, 
     MAX(CASE WHEN V.Item_Name='Item_Name_Two' THEN ItemPrice ELSE NULL END) Item_Price_Two, 
     MAX(CASE WHEN V.Item_Name='Item_Name_Three' THEN ItemPrice ELSE NULL END) Item_Price_Three 
    FROM Temp.View_Items V 
    WHERE V.ID       =   T.ID 
    AND V.Date       =   T.Date 
    ); 
+0

感谢戴夫,今天早上我试了一下,大大提高了性能。稍后我会看看11G支点,然后我会尝试为其他感兴趣的人更新此信息。再次感谢所有花时间回复的人。 – dee 2012-02-07 16:52:22

0
UPDATE TEMP_TABLE TI SET T.ItemPrice_One = 
     (
     SELECT ItemPrice 
     FROM Temp.View_Items V 
     WHERE V.Item_Name     =   'Item_Name_One' 
     AND V.ID       =   T.ID 
     AND V.Date       =   T.Date 
     ) 
,  T.ItemPrice_Two = 
     (
     SELECT ItemPrice 
     FROM Temp.View_Items V 
     WHERE V.Item_Name     =   'Item_Name_Two' 
     AND V.ID       =   T.ID 
     AND V.Date       =   T.Date 
     ) 
,  T.ItemPrice_Three = 
     (
     SELECT ItemPrice 
     FROM Temp.View_Items V 
     WHERE V.Item_Name     =   'Item_Name_Three' 
     AND V.ID       =   T.ID 
     AND V.Date       =   T.Date 
     ); 
+0

感谢您的回答,这个版本是否会提高性能?我会给它一个旋转,看看会发生什么。 – dee 2012-02-06 19:40:16

+0

我尝试了这一个,虽然它更清洁,但我没有注意到任何显着的改进。我仍然感激你的时间。谢谢 – dee 2012-02-07 16:53:33

1

也许你可以尝试探索利用MERGE语句的。它可能允许您避免对视图表执行三次扫描。我没有一个实例进行实验,但这里是思想的粗略估计:

MERGE INTO TEMP_TABLE t 
    USING (SELECT Item_name, ItemPrice 
      FROM Temp.View_Items V 
      WHERE V.Item_Name IN ('Item_Name_One', 'Item_Name_Two', 'Item_Name_Three') 
       AND V.ID = T.ID 
       AND V.Date = T.Date) s 
    ON (...join condition here... t.item_name = v.item_name??) 
    WHEN MATCHED THEN 
    UPDATE SET t.ItemPrice_One = DECODE(s.ItemPrice, 'Item_Name_One', v.ItemPrice, t.ItemPrice_One) 
       ,t.ItemPrice_Two = DECODE(s.ItemPrice, 'Item_Name_Two', v.ItemPrice, t.ItemPrice_Two) 
       ,t.ItemPrice_Three = DECODE(s.ItemPrice, 'Item_Name_Three', v.ItemPrice, t.ItemPrice_Three); 
+0

谢谢,就像我说过我在尝试合并前一段时间,我会根​​据我在这里看到的内容再次尝试。 – dee 2012-02-06 19:39:14

0

合并在这种情况下是最好的选择。