我有两张桌子说STOCK和ITEM。我们有一个查询从ITEM表中删除一些记录,
delete from ITEM where item_id not in(select itemId from STOCK)
现在我要删除超过15,00,000条记录,查询花了很多时间来进行操作。
当我搜索时,我发现了一些有效的方法来执行此操作。
单向:
创建表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;
其次,不要截断,只需删除ITEM,然后将ITEM_TEMP重命名为ITEM。但在这种情况下,我要重新创建所有索引。
任何人都可以建议上面哪一项效率更高,因为我无法在生产中查看。
答案 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方法没有任何问题。
我也不排除只运行有限行数的多次删除,特别是如果它在生产环境中。