【发布时间】:2010-10-06 05:00:50
【问题描述】:
当我尝试从包含两个 CLOB 字段的表中删除行时,我遇到了 Oracle 速度非常慢的问题。该表有数百万行,没有约束,删除是基于主键的。我重建了索引并重新计算了统计数据,但无济于事。
如何提高从该表中删除的性能?
【问题讨论】:
标签: sql oracle plsql oracle10g clob
当我尝试从包含两个 CLOB 字段的表中删除行时,我遇到了 Oracle 速度非常慢的问题。该表有数百万行,没有约束,删除是基于主键的。我重建了索引并重新计算了统计数据,但无济于事。
如何提高从该表中删除的性能?
【问题讨论】:
标签: sql oracle plsql oracle10g clob
跟踪它,启用等待
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_monitor.htm#i1003679
在 UDUMP 目录中找到跟踪文件。 TKPROF 吧。 看看最后,它会告诉你数据库在那个 SQL 期间花时间做什么。以下链接很好地概述了如何分析性能问题。
http://www.method-r.com/downloads/doc_download/10-for-developers-making-friends-with-the-oracle-database-cary-millsap
【讨论】:
使用 Oracle,您必须考虑在删除行时生成的重做量。如果 CLOB 字段非常大,由于写入的重做量很大,Oracle 可能需要一段时间才能删除它们,并且您可能无能为力。
您可以执行的一项测试是查看删除是否需要很长时间在一行中,其中两个 CLOB 字段都设置为空。如果是这种情况,那么可能是索引更新需要很长时间。如果是这种情况,如果删除非常频繁,您可能需要调查合并索引。
如果表是派生表,意思是可以从其他表重建,你可以看看表上的NOLOGGING选项。您可以使用最少的日志记录从源表重建表。
我希望这篇文章对一些人有所帮助,但更多细节可以帮助诊断问题。
【讨论】:
是否有任何引用该表的子表正在删除? (您可以从user_constraints 中进行选择,其中r_constraint_name = 您要从中删除的表上的主键名称)。
如果 Oracle 需要查看另一个表以检查没有子记录,删除可能会很慢。通常的做法是索引子表上的所有外键,所以这不是问题。
听从 Gary 的建议,执行跟踪并将 TKPROF 结果发布在这里,有人将能够提供进一步的帮助。
【讨论】:
您的UNDO 表空间在这种情况下似乎是瓶颈。
检查删除数据后创建ROLLBACK 需要多长时间。如果它所花费的时间与查询本身的时间相当(在50% 内),那么肯定是这种情况。
当您执行DML 查询时,您的数据(包括原始数据和更改数据)将写入重做日志,然后应用于数据文件和UNDO 表空间。
删除数百万行 CLOB 需要将数百兆字节(如果不是千兆字节)复制到 UNDO 表空间,这本身需要数十秒。
对此你能做些什么?
UNDO:将其放到单独的磁盘上,使其不那么稀疏(创建更大的数据文件)。ROLLBACK SEGMENTS 而不是托管UNDO,为此查询分配ROLLBACK SEGMENT,并在运行查询之前发出SET TRANSACTION USE ROLLBACK SEGMENT。如果不是这样,我。 e. ROLLBACK 的执行速度比查询本身快很多,然后尝试与您一起玩REDO 参数:
LOG_BUFFER 参数增加REDO 缓冲区大小。请注意,UNDO 操作也会生成 REDO,因此无论如何执行所有这些操作都很有用。
之前建议的NOLOGGING 没有用,因为它仅适用于列出的某些操作集here,DELETE 不是这些操作之一。
【讨论】:
删除的 CLOB 不会最终出现在 UNDOTBS 中,因为它们在 LOB 段中进行了版本控制和保留。我认为它会在撤消中产生一些 LOBINDEX 更改。
如果您之前将 LOB 设为 null 或清空,那么您是否真的通过提交与 DELETE 分开来测量该时间?如果您发出数千次删除,您是否使用批量提交?实例是否空闲?然后 AWR 报告应该告诉你发生了什么。
【讨论】: