2009-02-08 119 views
2

我遇到了一个问题,当我试图从包含两个CLOB字段的表中删除行时,Oracle非常慢。该表具有数百万行,没有限制,并且删除基于主键。我重建了索引和重新计算的统计数据,但无济于事。缓慢从Oracle 10g中的CLOB字段的表中删除

我该怎么做才能提高此表的删除性能?

回答

1

对于Oracle,您必须考虑删除行时生成的重做量。如果CLOB字段非常大,那么Oracle可能需要一段时间才能删除它们,因为正在写入的重做次数可能不多。

您可能要执行的测试是查看删除操作是否需要很长时间,其中两个CLOB字段都设置为null。如果是这样的话,那么索引更新可能需要很长时间。如果是这样,如果可能的话,您可能需要调查合并索引,如果删除频繁发生。

如果表是一个派生表,也就是说,它可以从其他表中重建,您可以查看表上的NOLOGGING选项。您可以用最少的日志记录从源表重建表。

我希望这个条目有助于一些,但一些更多的细节可以帮助诊断问题。

+0

谢谢尼克。我运行的最后一个测试是CLOB字段被清除,删除仍然很慢。只有两个索引,单列上的PK索引和单列上的FK索引。 这些索引与DB大小明智的其他索引没有任何区别。 – bitstream 2009-02-08 01:29:33

+0

有多少表有外键约束到你的表中?无论数量如何,您都希望检查这些表,即引用此表的ID是否已编入索引。如果他们不是这可能是你的问题的根源。 – Nick 2009-02-08 19:14:15

2

跟踪它,以等待启用

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 
+0

非常酷。我今天要试一试。谢谢! – bitstream 2009-02-09 15:14:36

1

是否有任何引用此表的表的子表正在从中删除? (您可以从user_constraints中进行选择,其中r_constraint_name =您要删除的表上的主键名)。

如果Oracle需要查看另一个表以检查是否存在子记录,则删除操作可能会很慢。通常的做法是索引子表上的所有外键,所以这不是问题。

按照加里的建议,执行跟踪并发布TKPROF结果,这里有人可以进一步提供帮助。

1

你的UNDO表空间似乎是这种情况下的瓶颈。

检查删除数据后需要多长时间才能生成ROLLBACK。如果需要花费时间与查询本身的时间相比(在50%之内),那肯定就是这种情况。

当您执行DML查询时,您的数据(包括原始数据和已更改数据)将写入重做日志,然后应用于数据文件和表空间。

删除数百万行CLOB行需要将几百MB(如果不是千兆字节)复制到UNDO表空间,该表空间本身需要几十秒。

你能做些什么呢?

  1. 创建一个更快的UNDO:把它放在一个单独的磁盘上,使其稀疏(创建一个更大的数据文件)。
  2. 使用ROLLBACK SEGMENTS而不是托管UNDO,为此查询分配ROLLBACK SEGMENT,并在运行查询之前发出SET TRANSACTION USE ROLLBACK SEGMENT

如果不是这样,我。即ROLLBACK执行更快,查询本身,然后尝试用你REDO参数玩:

  1. 使用LOG_BUFFER参数来增加您的REDO缓冲区的大小。
  2. 增加日志文件的大小。
  3. 在独立的磁盘上创建日志文件,以便从第一个数据文件读取不会妨碍写入第二个数据文件等。

请注意,UNDO操作也会生成REDO,所以无论如何这么做都很有用。

NOLOGGING之前提出的建议是无用的,因为它仅适用于列出的某些操作集here,DELETE不属于这些操作之一。

0

已删除的CLOB不会在UNDOTBS中结束,因为它们在LOB段中进行了版本控制和回收。我认为它会在撤消中产生一些LOBINDEX变化。

如果您之前为空或清空LOB,那么您是否已使用单独的DELETE实际测量了该时间?如果您发出数千次删除,您是否使用批量提交?实例是否空闲?然后AWR报告应该告诉你发生了什么事情。