我有一个运行良好但需要很长时间才能完成的更新语句。
我在一个表中更新了大约 150 行,通过视图暴露了数万行。有人建议我使用 Partition By 子句来加快进程。
我对 Partition By 语句不太熟悉,但我一直在环顾四周,我想也许我需要使用一个具有可以比较的数值的字段。
它是否正确?或者我可以用其他东西对更大的表进行分区吗?
如果是这种情况,我正在为更大的表格中可以使用的东西而苦苦挣扎。该表的组成如下。
ID 的类型为 NUMBER,并为特定项目创建唯一 ID。Start_Date 具有日期类型,表示 ID 有效时的开始。结束日期具有日期类型,并指示 ID 不再有效的结束时间。ID_Type 是 NVARCHAR2(30) 并指示我们使用的标识符类型。ID_Type2 是 NVARCHAR2(30) 并指示我们正在使用的 Identifier 的 sub_type。标识符是 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'));
提前感谢您对我的问题的任何方面的任何建议。
附加信息***
在调查并遵循 Gordon 的建议后,我将更新更改为三个更新。这将整个更新过程减少了 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,我从我的 UPDATE 中删除了 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;
再次感谢。