如何回收已删除LOB的存储空间

时间:2010-06-14 16:08:55

标签: oracle

我有一个LOB表空间。目前持有9GB的12GB可用。而且,据我所知,删除记录不会回收表空间中的任何存储。 (这是通过监视存储的简单方法 - 针对user_extents的查询,这是我作为非DBA所允许的所有内容)我担心处理进一步处理。

我担心的是空间不足 - 我们在12GB的桌面空间可用大约9 GB,我想知道如何在要求更多空间之前回收空间。

LOB列存储在单独的表空间中,但允许“存储在行中”用于小型表空间。

这是Oracle 11.1,数据位于同一个表中的CLOB和BLOB列中。 LOB索引段(SYS_IL ...)很小,所有存储都在数据段中(SYS_LOB ...)

我们试过purge和coalesce并没有得到任何地方 - 在user_extents中的字节数相同。

“Alter table xxx move”将起作用,但是我们需要将某个地方移动到有足够空间容纳修改后的数据。当然,我们还需要在非工作时间完成这项工作并重建索引,但这很容易。

复制好数据并进行截断,然后将其复制回来也是有效的。但这几乎就是“alter table”命令的作用。

我是否遗漏了一些简单的方法来缩减内存并恢复存储?或者是“改变表xxx移动”的最佳方法?或者这是不是问题,Oracle会在需要时从删除的lob行中获取空间吗?

2 个答案:

答案 0 :(得分:9)

这个问题已经很久了,但从来没有一个有效的答案,可能对很多人有用,所以这里我遇到了解决这个问题的解决方案。

你是对的,删除LOB不会收回桌面中的任何存储空间。

在删除LOB之前和之后运行此查询将得到相同的结果

select bytes
    from user_segments
    where tablespace_name = yourTableSpace
      and segment_name = yourTableName; 

阅读this Oracle doc,我发现你需要执行以下语句

ALTER TABLE yourLobTable MODIFY LOB (yourLobColumn) (SHRINK SPACE);

这会缩小BASICFILE LOB段。

现在,如果您重新执行查询

select bytes
    from user_segments
    where tablespace_name = yourTableSpace
      and segment_name = yourTableName; 

您会注意到该空间已释放到表空间,并且可以根据需要重复使用该空间。

现在,对于那些想要释放磁盘空间的用户,请注意数据文件不会自动重新调整大小,并且仍会保留磁盘上的完整大小。

但在重新调整数据文件大小之前,请确保使用这些查询释放段中未使用的空间(使用前面所述的相同文档窃取它)(使用您需要的那个)

ALTER TABLE table DEALLOCATE UNUSED KEEP integer;
ALTER INDEX index DEALLOCATE UNUSED KEEP integer;
ALTER CLUSTER cluster DEALLOCATE UNUSED KEEP integer;

请注意,KEEP子句是可选的,允许您指定段中保留的空间量。您可以通过检查DBA_FREE_SPACE视图来验证是否释放了已释放的空间。

现在重新调整数据文件的大小,

ALTER DATABASE DATAFILE yourDatafile.dbf resize 500M

请注意,调整大小时可以缩小的最大大小取决于数据文件中最后一个数据块的位置。因此,在删除大量数据之后,很有可能无法真正重新调整大小。然后,最简单的方法是导出数据并在另一个表空间中重新导入,然后删除旧的表空间。导入数据时,Oracle会尽可能地打包它们。

如果你想释放更多的空间,你可以清除临时表空间,有时会占用大量空间(我的数据库为5GB)。使用以下语句检查其大小:

SELECT tablespace_name, file_name, bytes
  FROM dba_temp_files WHERE tablespace_name like 'TEMP%';

答案 1 :(得分:1)

通常,一旦将范围分配给表,它就会保持分配状态。如果将其他数据插入表中,则可以重用表中的空白区域。然而,很难从表中回收空间,因为该表可能具有例如块1到100,并且空块在块50-75中,或者空块是1,3,5,7等。

问题是,您是否担心在表中重用空间,或者您是否需要为表空间中的其他对象释放空间,或者您是否需要能够缩小表空间数据文件?