UPDATE [TABLE] SET [FIELD]=0 WHERE [FIELD] IS NULL
[TABLE]是一个超过7亿行的Oracle数据库表。我在运行6小时后取消了SQL执行。
是否有任何SQL提示可以提高性能?或任何其他解决方案来加快速度?
编辑:此查询将运行一次,然后再不会运行。
答案 0 :(得分:10)
首先是一次性查询还是循环查询?如果您只想在并行模式下查看运行查询,则必须执行此操作。您无论如何都必须扫描所有行,您可以使用ROWID(自己动手并行)范围自行划分工作负载,也可以使用Oracle内置功能。</ p>
假设您想要经常运行它并想要优化此查询,那么field
列为NULL的行数最终会比总行数小。在这种情况下,索引可以加快速度。 Oracle不会将所有索引列的行编入为NULL,因此查询不会使用field
上的索引(因为您要查找field
为NULL的所有行)。
或者:
(FIELD, 0)
上创建索引,0
将充当非NULL伪列,并且所有行都将在表格上编入索引。在(CASE WHEN field IS NULL THEN 1 END)
上创建一个基于函数的索引,这只会索引为NULL的行(索引因此非常紧凑)。在这种情况下,您将不得不重写您的查询:
UPDATE [TABLE] SET [FIELD]=0 WHERE (CASE WHEN field IS NULL THEN 1 END)=1
由于这是一次性方案,您可能需要使用PARALLEL
提示:
SQL> EXPLAIN PLAN FOR
2 UPDATE /*+ PARALLEL(test_table 4)*/ test_table
3 SET field=0
4 WHERE field IS NULL;
Explained
SQL> select * from table( dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4026746538
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 22793 | 289K| 12 (9)| 00:00:
| 1 | UPDATE | TEST_TABLE | | | |
| 2 | PX COORDINATOR | | | | |
| 3 | PX SEND QC (RANDOM)| :TQ10000 | 22793 | 289K| 12 (9)| 00:00:
| 4 | PX BLOCK ITERATOR | | 22793 | 289K| 12 (9)| 00:00:
|* 5 | TABLE ACCESS FULL| TEST_TABLE | 22793 | 289K| 12 (9)| 00:00:
--------------------------------------------------------------------------------
答案 1 :(得分:5)
其他用户是否同时更新表中的相同行?
如果是这样,您可能会遇到很多并发问题(等待锁定),并且可能值得将其分解为较小的事务。
DECLARE
v_cnt number := 1;
BEGIN
WHILE v_cnt > 0 LOOP
UPDATE [TABLE] SET [FIELD]=0 WHERE [FIELD] IS NULL AND ROWNUM < 50000;
v_cnt := SQL%ROWCOUNT;
COMMIT;
END LOOP;
END;
/
ROWNUM限制越小,您遇到的并发/锁定问题就越少,但您在表扫描中花费的时间就越多。
答案 2 :(得分:3)
文森特已经完全回答了你的问题,但我很好奇这一行动背后的“原因”。为什么要将所有NULL更新为0?
此致 罗布。
答案 3 :(得分:1)
一些建议:
在运行UPDATE语句之前删除包含FIELD的所有索引,然后再重新添加它们。
编写一个PL / SQL过程来执行此操作,该过程在每1000或10000行之后提交。
希望这有帮助。
答案 4 :(得分:0)
通过使用ALTER表将列“DEFAULT”值设置为0,您可以在不进行更新的情况下获得相同的结果。