【问题标题】:Deleting records in table contains 180 Million in oracleoracle中删除表中包含1.8亿条记录
【发布时间】:2014-05-15 06:25:59
【问题描述】:

朋友们,

我有订单表,每个表中至少有 1 亿条记录。我们有一个正在运行的作业,它调用一个存储过程,该过程每天删除至少 50K(MIN)和 200K(MAX)条记录。

我目前正在使用 SQL BULK COLLECT 从表中删除记录。目前删除 50K 需要 4 个多小时,速度非常慢。

在谷歌搜索后,找出CTAS方法,即创建表并保留我们想要的记录并删除现有的记录并重命名临时表。我不能这样做,因为这个选项不被接受,因为表格更重要。

您能否提出一些解决方案来提高其性能?

提前致谢!!

【问题讨论】:

  • 被删除的 50K 记录是什么?选择删除记录的依据是什么?
  • “从 where 中删除”有什么问题?批量收集有什么用?
  • 我正在使用 FORALL 来删除。正在根据时间戳删除记录。
  • Rene- 一条一条删除记录会花费更多时间,尤其是表包含 1.8 亿条记录。它还会生成更多重做和撤消日志。如果我错了,请纠正我?
  • 4 小时删除 50K 行似乎太长了,不管行是如何删除的。您应该分析和监视您的代码,以准确了解时间花在哪里。是否存在错误的连接导致行选择永远需要?该表是否有几十个索引导致删除速度很慢?

标签: sql oracle stored-procedures oracle-sqldeveloper sql-tuning


【解决方案1】:

假设您有足够的物理磁盘空间来复制数据,您可以使用以下方法(我假设您的表称为 ORDERS):

  • 使用CREATE TABLE orders_b AS SELECT * FROM orders 创建订单表的副本 ORDER_B
  • 将原始表重命名为 ORDERS_A:ALTER TABLE orders RENAME TO orders_a
  • 创建一个名为 ORDERS 的同义词指向 ORDERS_A:CREATE SYNONYM orders FOR order_a

到目前为止,一切都很好。您的客户端代码现在使用同义词 ORDERS 而不是物理表。 现在是有趣的部分(每日刷新程序):

  • 截断 ORDERS_B
  • INSERT /*+APPEND+*/ 填写 ORDERS_B(您可能还想尝试 PARALLEL 提示)
  • 将同义词 ORDERS 切换为指向 ORDERS_B
  • 第二天:用 ORDERS_A 代替 ORDERS_B 重复
  • 无限重复

或者,您可以删除表并重新创建它,而不是使用 TRUNCATE/INSERT。这需要更多的工作,因为您还必须重新创建索引和授权。

这种技术称为同义词切换 - 您可能需要阅读 Tyler Muth's article about synonym switching 以获得更完整的解释。

【讨论】:

  • Frank- 确实是一个很好的解决方案 但是,正如我在我的第一篇文章中提到的那样,我提出了同样的建议,这是一个可供客户 24 X 7 使用的交易表,因此该建议被拒绝了
  • @Prabhu 使用这种方法,数据 24x7 提供
  • 同意 Frank,但商业拒绝了这种方法。
  • 我认为这不是一个合适的解决方案 - 不适合这么大的桌子。
【解决方案2】:

删除记录的条件是什么?

也许您可以在此表上创建基于函数的索引。然后,您可以使用一个简单的删除语句删除记录。或者考虑一下表分区。如果您的分区键很智能并且涵盖了删除条件,您可以在几秒钟内删除或清除旧分区。

顺便说一句,使用包DBMS_REDEFINITION,即使不中断服务,您也可以将“正常”表更改为分区表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-29
    • 2021-08-02
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多