当我尝试从包含两个 CLOB 字段的表中删除行时,我遇到了 Oracle 速度非常慢的问题。该表有数百万行,没有约束,删除是基于主键的。我重建了索引并重新计算了统计数据,但无济于事。
我可以做些什么来提高从此表中删除的性能?
跟踪它,启用等待
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
在这种情况下,您的UNDO
表空间似乎是瓶颈。
ROLLBACK
检查删除数据后需要多长时间。如果它所花费的时间与查询本身的时间相当(在 内50%
),那么肯定是这种情况。
当您执行DML
查询时,您的数据(包括原始数据和更改数据)将写入重做日志,然后应用于数据文件和UNDO
表空间。
删除数百万CLOB
行需要将数百兆字节(如果不是千兆字节)复制到UNDO
表空间,这本身需要数十秒。
你能做些什么呢?
UNDO
:将其放在单独的磁盘上,使其不那么稀疏(创建更大的数据文件)。ROLLBACK SEGMENTS
而不是 managed ,在运行查询之前为这个查询和问题UNDO
分配一个。ROLLBACK SEGMENT
SET TRANSACTION USE ROLLBACK SEGMENT
如果不是这种情况,即ROLLBACK
执行比查询本身快得多,那么尝试使用您的REDO
参数:
REDO
缓冲区大小。LOG_BUFFER
请注意,UNDO
操作也会生成REDO
,因此无论如何执行所有这些操作都是有用的。
NOLOGGING
之前建议是无用的,因为它仅适用于此处列出的某些操作集,DELETE
而不是这些操作之一。
使用 Oracle,您必须考虑删除行时生成的重做量。如果 CLOB 字段非常大,由于写入的重做量,Oracle 可能需要一段时间才能删除它们,并且您可能无能为力。
您可以执行的一项测试是查看删除是否需要很长时间在一行中,其中两个 CLOB 字段都设置为空。如果是这种情况,那么可能是索引更新需要很长时间。如果是这种情况,如果删除非常频繁,您可能需要调查合并索引(如果可能)。
如果表是派生表,意思是可以从其他表重建,可以看表的NOLOGGING选项。您可以使用最少的日志记录从源表重建表。
我希望这篇文章对一些人有所帮助,但是更多细节可以帮助诊断问题。
是否有任何引用该表的子表正在删除?(您可以在要从中删除的表上选择user_constraints
where = primary key name)。r_constraint_name
如果 Oracle 需要查看另一个表以检查没有子记录,则删除可能会很慢。通常的做法是索引子表上的所有外键,所以这不是问题。
遵循 Gary 的建议,执行跟踪并将 TKPROF 结果发布在这里,有人将能够提供进一步的帮助。
删除的 CLOB 不会最终出现在 UNDOTBS 中,因为它们在 LOB 段中进行了版本化和保留。我认为它会在撤消中产生一些 LOBINDEX 更改。
如果您之前将 LOB 清空或清空,您是否真的用 DELETE 分开的提交来测量那个时间?如果您发出数千次删除,您是否使用批量提交?实例是否空闲?然后 AWR 报告应该告诉你发生了什么。