我应该在Oracle Partition By子句中使用哪个字段来提高性能

时间:2012-08-08 13:53:36

标签: sql oracle sql-update database-partitioning

我有一个工作正常的更新声明,但需要很长时间才能完成。

我在一个表中更新大约150行,通过视图暴露了数万行。有人建议我使用Partition By子句来加速这个过程。

我对Partition By语句不太熟悉,但我一直在四处寻找,我想我可能需要使用一个具有可以比较的数值的字段。

这是对的吗?或者我可以用其他东西对较大的表进行分区吗?

如果是这种情况,我正在努力使用更大的表中的内容。该表的组成如下。

ID的类型为NUMBER,并为特定项目创建唯一ID。 Start_Date具有日期类型,表示ID有效时的开始。 结束日期具有日期类型,表示ID停止生效的结束时间。 ID_Type是NVARCHAR2(30)并指示我们使用的标识符类型。 ID_Type2是NVARCHAR2(30)并指示我们正在使用的标识符的子类型。 标识符是NVARCHAR2(30),任何一个ID都可以映射到一个或多个标识符。

例如 - View_ID

ID | Start_Date | End_Date   | ID_Type1| ID_Type2 | Identifier
1  | 2012-01-01 | NULL       | Primary | Tertiary | xyz1
1  | 2012-01-01 | NULL       | Second  | Alpha    | abc2
2  | 2012-01-01 | 2012-01-31 | Primary | Tertiary | ghv2
2  | 2012-02-01 | NULL       | Second  | Alpha    | mno4

只要存在id按日期有效的子句,是否可以通过此视图的ID字段进行分区?

更新语句是非常基本的,尽管它选择了几种可能的标识符和ID_Type1之一。

UPDATE Temp_Table t set ID = 
(SELECT DISTINCT ID FROM View_ID v
 WHERE inDate BETWEEN Start_Date and End_Date
 AND v.Identifier = (NVL(t.ID1, NVL(t.ID2, t.ID3)))
 AND v.ID_Type1 in ('Primary','Secondary'));

提前感谢您就我的问题的任何方面提出任何建议。

其他信息 ***

在调查并遵循戈登的建议后,我将更新更改为三次更新。这使整个更新过程从一分钟内缩短了75%,只有20多秒。这是一个很大的改进,但如果可能的话,我想更多地减少这个过程。

有人认为Partition By条款会更进一步吗?如果是这样,将此子句放入更新语句的正确方法是什么。老实说,我不确定我是否理解这条款的运作方式。

如果使用SELECT语句的UPDATE只允许选择1个值,那么这会排除类似以下内容吗?

UPDATE Temp_Table t SET t.ID = 
(SELECT DISTINCT ID,
        Row_Number () (OVER PARTITION BY ID_Type1) AS PT1
 FROM View_ID v
 WHERE inDate BETWEEN v.Start_Date and v.End_Date
 AND v.Identifier = t.ID1
 AND PT1.Row_Number = 1 )

*溶液* * ** * ** * ****

我结合以下两个响应者的建议,以显着提高性能。来自Gordon我从我的更新中删除了NVL并将其更改为三个单独的更新。 (我更喜欢将它们组合成一个案例,但我的试验仍然很慢。)

从Eggi,我看起来使用某种物化视图,我可以实际索引自己并确定一个WITH子句。

UPDATE Temp_Table t set ID = 
(WITH IDs AS (SELECT /*+ materialize */ DISTINCT ID, Identifier FROM View_ID v
 WHERE inDate BETWEEN Start_Date and End_Date
 AND v.Identifier = ID1)
 SELECT g.ID FROM IDs g
 WHERE g.Identifier = t.ID1;

再次感谢。

2 个答案:

答案 0 :(得分:1)

分区的最佳选项似乎是开始日期,因为它似乎总是有一个值,你也可以在查询中将它作为输入参数。

如果你还没有这样做,我会在ID_Type1上添加一个位图索引。

答案 1 :(得分:1)

很难想象windows / analytic函数如何帮助进行此更新。我强烈建议你学习它们,但不是为了这个目的。

也许建议是分区用于表的表空间。请注意,非常与"分区不同,"语句,通常指窗口/分析函数。表空间分区可能有助于提高性能。但是,您可以尝试以下其他方法。

我认为你的问题是临时表和视图之间的连接。据推测,您正在创建临时表。您应该添加一个新列,比如UsedID,其定义为:

coalesce(t.ID1, t.ID2, t.ID3) as UsedId

" WHERE"更新中的子句将是:

WHERE inDate BETWEEN Start_Date and End_Date AND
      v.Identifier = t.UsedId AND
      v.ID_Type1 in ('Primary', 'Secondary')

我怀疑性能问题是在连接中使用NVL,这会干扰优化策略。

回应你的评论。 。 。您的原始查询与此版本具有相同的问题。也许你想要的逻辑是:

WHERE inDate BETWEEN Start_Date and End_Date AND
      v.Identifier in (t.ID1, t.ID2, t.ID3) AND
      v.ID_Type1 in ('Primary', 'Secondary')