如何加速Oracle 11g中的更新?

时间:2015-02-28 21:16:02

标签: sql oracle11g

我正在对包含950万条记录的表(Table_A)进行更新。我已经运行了13个小时,但还没有完成!在如何加快速度方面,有人能指出我正确的方向吗?我可以使用PL / SQL将子选项存储到变量中,如果这样可以使它更快。我是甲骨文新手,非常感谢任何帮助。

update Table_A
set STATUS='DELETED', DESC='REDACTED', NAME=dbms_random.string('A', 20)
where Table_B_ID in (
    select ID
    from Table_B
    where Table_C_ID in (
        select ID
        from Table_C
        where XYZ_ID!=56
    )
);

Table_A有950万条记录 Table_B有430,000条记录
Table_C有3050个记录

4 个答案:

答案 0 :(得分:1)

尝试使用EXISTS而不是列表来编写两个子查询。它的性能要高得多。

请参阅此处进行讨论:https://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:442029737684

编辑2015-03-02 这是一个使用exists的(希望是正确的)查询:

UPDATE Table_A A
   SET A.STATUS='DELETED', A.DESC='REDACTED', A.NAME=dbms_random.string('A', 20)
 WHERE EXISTS (
    SELECT 1
      FROM Table_B B
     WHERE A.Table_B_ID = B.ID
       AND EXISTS(
        SELECT 1
          FROM Table_C C
         WHERE C.XYZ_ID!=56
           AND B.Table_C_ID = C.ID
       )
 );

答案 1 :(得分:0)

首先在table_b上为Table_C_ID创建索引,

然后创建3个表的统计信息,

dbms_stats.gather_table_stats('OWNER', 'TABLE_A');
dbms_stats.gather_table_stats('OWNER', 'TABLE_B');
dbms_stats.gather_table_stats('OWNER', 'TABLE_C');

之后使用paralell提示:

update /*+parallel(8)*/Table_A
set STATUS='DELETED', DESC='REDACTED', NAME=dbms_random.string('A', 20)
where Table_B_ID in (
    select ID
    from Table_B
    where Table_C_ID in (
        select ID
        from Table_C
        where XYZ_ID!=56
    )
);

那些会更好地提高速度

答案 2 :(得分:0)

相应的select多长时间?

select a.*
from Table_A
where Table_B_ID in (select ID
                     from Table_B
                     where Table_C_ID in (select ID
                                          from Table_C
                                          where XYZ_ID <> 56
                                         )
                    );

据推测,这并不快,我的猜测是由于缺乏索引而不快。对于此查询,我建议使用以下复合索引:table_b(Table_C_ID, ID)table_c(xyz_id, id)。我建议您在使用select之前让update快速工作。

请注意,这只是猜测。例如,您可以更新Table_A中的每一行,这是一个真正的性能值。或者,一个或多个表上可能存在锁定导致数据争用。

答案 3 :(得分:0)

感谢大家的建议。我一次尝试一次。

在所有情况下,显然使用existsin不同。例如,如果我将in替换为exists

,则以下查询会返回不同的结果
update Table_A
set STATUS='DELETED', DESC='REDACTED', NAME=dbms_random.string('A', 20)
where exists (
    select ID
    from Table_B
    where exists (
        select ID
        from Table_C
        where XYZ_ID!=56
    )
);