多个小删除

时间:2016-12-03 00:55:43

标签: sql oracle indexing

我有一个PL / SQL脚本循环遍历人的记录(约400万)并执行多个更新(~100)和一个删除语句(所有这些更新和删除都在不同的表上)。我面临的问题是,一个delete语句本身需要大约一半的运行时间。我知道当你执行一个删除语句时,它需要更新索引,但我觉得它很荒谬。我目前正在使用dbms_parallel_execute使用一个线程测试此脚本,但我计划多线程处理此脚本。

我正在执行类似于以下内容的查询:

DELETE FROM table1 t1
WHERE (t1.key1, t1.key2) IN (SELECT t2.key1, t2.key2
                               FROM table2 t2
                              WHERE t2.parm1 = 1234
                                AND t2.parm2 = 5678).

以下事实:

  • 表2(约3000万条记录)比table1(约300万条记录)大约10倍。
  • table1(key1,key2)
  • 上有一个主键
  • table2(key1,key2)
  • 上有一个主键
  • table2(parm1,parm2)
  • 上有索引
  • 我已禁用table1(key1,key2)上引用table2(key1,key2)的外键约束
  • table1没有其他限制,但对table2有更多约束。

  • 已禁用table1上的所有触发器

  • 此查询的解释计划的成本低于我的许多更新语句的成本(但我知道这并不是很重要)。

解释计划输出:

    OPERATION                            OPTIONS                                                                                              OBJECT_INSTANCE                              OBJECT_TYPE                          OPTIMIZER                                                                                            SEARCH_COLUMNS                               ID                                           PARENT_ID                                    DEPTH                                        POSITION                                     COST                                         CARDINALITY                                  BYTES                                        CPU_COST                                     IO_COST                                      TIME                                         
------------------------------------ ---------------------------------------------------------------------------------------------------- -------------------------------------------- ------------------------------------ ---------------------------------------------------------------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- 
DELETE STATEMENT                                                                                                                                                                                                            ALL_ROWS                                                                                                                                                                                     0                                                                                         0                                            5                                            5                                            1                                           36                                        38043                                            5                                            1 
DELETE                                                                                                                                                                                                                                                                                                                                                                                                                   1                                            0                                            1                                            1                                                                                                                                                                                                                                                                               
NESTED LOOPS                                                                                                                                                                                                                                                                                                                                                                                                             2                                            1                                            2                                            1                                            5                                            1                                           36                                        38043                                            5                                            1 
TABLE ACCESS                         BY INDEX ROWID                                                                                                                                  2 TABLE                                ANALYZED                                                                                                                                                                                     3                                            2                                            3                                            1                                            4                                            1                                           25                                        29022                                            4                                            1 
INDEX                                RANGE SCAN                                                                                                                                        INDEX                                ANALYZED                                                                                                                                        1                                            4                                            3                                            4                                            1                                            3                                            1                                                                                     21564                                            3                                            1 
INDEX                                UNIQUE SCAN                                                                                                                                       INDEX (UNIQUE)                       ANALYZED                                                                                                                                        2                                            5                                            2                                            3                                            2                                            1                                            1                                           11                                         9021                                            1                                            1

我想知道是否有办法让这个删除更快。我尝试做bulk delete,但似乎没有改善运行时间。如果有任何方法可以执行所有删除,然后更新索引,我怀疑它会运行得更快。显然,从select中创建一个create table是不可能的,因为我正在从另一个表循环遍历记录(并运行多个条件)来进行删除。

2 个答案:

答案 0 :(得分:0)

您的每次删除调用,在表2中的30m记录上运行查询,这肯定会降低性能并且还可能会产生锁定问题,从而再次降低查询速度。

我建议移出从table2中选择数据的内联查询。表2应该驱动删除并删除候选记录。它可以作为游标运行或将此数据放在临时表中。让删除在500,1000的块中执行,然后提交。可以根据结果优化此块。

删除期间的索引更新不是多余的,如果此进程在非工作时间运行,您可以禁用索引并重新创建..

答案 1 :(得分:0)

我认为如果外部查询是“小”而内部查询是“大” - 那么WHERE EXISTS可以非常高效。

尝试where where子句而不是In子句,然后检查解释计划和性能。

DELETE FROM table1 t1
WHERE
Exists (select 1 
   FROM table2 t2
  WHERE t2.parm1 = 1234
 AND t2.parm2 = 5678
 AND t2.key1 = t1.key1
 AND t2.key2 = t1.key2
)