以有效的方式删除记录

时间:2015-04-25 06:55:04

标签: oracle

我有两张桌子说STOCK和ITEM。我们有一个查询从ITEM表中删除一些记录,

delete from ITEM where item_id not in(select itemId from STOCK)

现在我要删除超过15,00,000条记录,查询花了很多时间来进行操作。

当我搜索时,我发现了一些有效的方法来执行此操作。

  1. 单向:

    创建表ITEM_TEMP AS SELECT * FROM ITEM WHERE item_id in(从STOCK中选择itemId);

    TRUNCATE TABLE ITEM;

    INSERT / + APPEND + / INTO ITEM SELECT * FROM ITEM_TEMP; DROP TABLE ITEM_TEMP;

  2. 其次,不要截断,只需删除ITEM,然后将ITEM_TEMP重命名为ITEM。但在这种情况下,我要重新创建所有索引。

  3. 任何人都可以建议上面哪一项效率更高,因为我无法在生产中查看。

3 个答案:

答案 0 :(得分:1)

从已用空间(和高水印)和性能的最佳方式是删除表,然后重命名ITEM_TEMP表。但是,正如您所提到的,之后您需要重新创建索引(也包括授权,触发器,约束)。此外,所有依赖对象都将失效。

有时我尝试按部分删除:

begin
  loop
    delete from ITEM where item_id not in(select itemId from STOCK) and rownum < 10000;
    exit when SQL%ROWCOUNT = 0;
    commit;
  end loop;
end;

答案 1 :(得分:1)

由于行数非常多,最好使用分区表,可能是“itemId”上的List分区。然后你可以轻松放下一个分区 此外,如果您的应用程序运行得更快这需要改变设计,但从长远来看会带来好处。

答案 2 :(得分:1)

我认为正确的方法取决于您的环境,在这里。

如果您对该表具有不得受影响的权限,或者至少必须在删除该表时进行恢复,则INSERT / * + APPEND * /可能更加可靠。触发器,类似地,或外键,或者在删除基表时将自动删除的任何对象(当然,外键会使截断变得复杂)。

我通常会根据它来选择truncate和insert方法。不要担心表上索引的存在 - 直接路径插入在构建它们时非常有效。

但是,如果你有一个没有依赖对象的简单表,那么drop-and-rename方法没有任何问题。

我也不排除只运行有限行数的多次删除,特别是如果它在生产环境中。