Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何优化在具有700M行的Oracle表上运行的更新SQL_Sql_Performance_Oracle_Oracle10g - Fatal编程技术网

如何优化在具有700M行的Oracle表上运行的更新SQL

如何优化在具有700M行的Oracle表上运行的更新SQL,sql,performance,oracle,oracle10g,Sql,Performance,Oracle,Oracle10g,[TABLE]是一个Oracle数据库表,有超过7亿行。在SQL运行了6个小时后,我取消了它的执行 是否有任何SQL提示可以提高性能?或者有其他的解决方案来加速 编辑:此查询将运行一次,然后再也不会运行。通过使用ALTER table将列“DEFAULT”值设置为0,您可以在不进行更新的情况下获得相同的结果。首先,它是一次性查询还是重复查询?如果您只需要执行一次,那么您可能希望在并行模式下运行查询。无论如何,您都必须扫描所有行,您可以使用ROWID的范围来划分工作负载(自己动手并行),也可以使用

[TABLE]是一个Oracle数据库表,有超过7亿行。在SQL运行了6个小时后,我取消了它的执行

是否有任何SQL提示可以提高性能?或者有其他的解决方案来加速


编辑:此查询将运行一次,然后再也不会运行。

通过使用ALTER table将列“DEFAULT”值设置为0,您可以在不进行更新的情况下获得相同的结果。

首先,它是一次性查询还是重复查询?如果您只需要执行一次,那么您可能希望在并行模式下运行查询。无论如何,您都必须扫描所有行,您可以使用ROWID的范围来划分工作负载(自己动手并行),也可以使用Oracle内置功能

假设您希望经常运行它并希望优化此查询,则
字段
列为NULL的行数最终将比总行数小。在这种情况下,索引可以加快速度。Oracle不会将所有索引列均为NULL的行编入索引,因此您的查询不会使用
字段
上的索引(因为您希望查找
字段
为NULL的所有行)

要么:

  • (字段,0)
    上创建索引,
    0
    将充当非空伪列,并且表上的所有行都将被索引
  • 上创建基于函数的索引(如果字段为NULL,则为1 END)
    ,这将只索引为NULL的行(因此索引将非常紧凑)。在这种情况下,您必须重写查询:

    UPDATE[TABLE]SET[FIELD]=0,其中(字段为空时为1 END)=1

编辑: 由于这是一个一次性场景,您可能需要使用
PARALLEL
提示:

UPDATE [TABLE] SET [FIELD]=0 WHERE [FIELD] IS NULL

文森特已经完美地回答了你的问题,但我很好奇这次行动背后的“原因”。为什么要将所有NULL更新为0

问候,, Rob.

一些建议:

  • 在运行UPDATE语句之前,删除包含字段的所有索引,然后稍后重新添加它们

  • 编写一个PL/SQL过程来执行此操作,每1000或10000行提交一次


  • 希望这有帮助。

    其他用户是否同时更新表中的相同行

    如果是这样,您可能会遇到很多并发性问题(等待锁),将其分解为较小的事务可能是值得的

    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:
    --------------------------------------------------------------------------------
    
    声明
    v_cnt编号:=1;
    开始
    当v_cnt>0循环时
    更新[表格]设置[字段]=0,其中[字段]为空且ROWNUM<50000;
    v_cnt:=SQL%ROWCOUNT;
    犯罪
    端环;
    结束;
    /
    

    ROWNUM限制越小,并发/锁定问题就越少,但扫描表的时间就越多。

    您好,这是一个一次性查询。但是,感谢您在回答中涵盖了这两种情况(一次性查询/重复查询)。很好地使用了解释计划示例,这会更快吗?它会更快,因为它不会以任何方式更新表数据,只更新表定义OK,但在这种情况下,我必须更新现有的行,而不仅仅是表定义。不,您是在告诉Oracle在遇到NULL时传递默认值零而不是NULL值——所有这些都发生在选择处理上,实际表没有更新。-1抱歉,这不起作用。更改默认值不会更新现有行。(在Oracle 11g中,只有在一次操作中添加了一个新列,该列同时具有默认值和NOTNULL约束,这种“廉价更新”技巧才有效。)问得好,Rob。这是因为在普通索引中不跟踪空值。在这种情况下,执行更新和更改数据的语义似乎相当激烈。您可以创建一个基于函数的索引,或者在([field],1)上创建一个常规索引。是的,这是我们一直在考虑的一种方法。感谢您确保在更新后添加NOTNULL约束,这样您就不必再这样做了。
    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;
    /