在 Oracle 11g 版上:
谷歌搜索后,我找不到删除表后回收可用空间的简单方法。
我找到了很多解释,说明数据文件如何变得碎片化,为了移动数据文件末尾的“空白空间”而必须运行的大量无聊查询(逐表......即使你有 200 张桌子!?)。
然后你必须通过“猜测”你可以减少多少来减少数据文件的大小,或者你必须确切地知道你的“块大小”是多少......最后你不应该忘记“重建索引”。
参见例如:http : //asktom.oracle.com/pls/asktom/f?p=100 :11:0 ::::P11_QUESTION_ID : 54178027703899
和http://www.oracle-base.com/articles/misc/ReclaimingUnusedSpace.php
是否有一个简单的 PL/SQL 过程,给定一个表空间名称或数据文件名称,可以完成这项工作?或任何类似的 Oracle 工具?
简短的回答是否定的。不幸的是,在 Oracle 中执行此操作的方法确实需要“大量无聊的查询”。您链接到的文章是有关该主题的一些最佳信息。数据文件确实会变得碎片化,因此即使最高段下方存在可用空间,Oracle 也不会在RESIZE
完成后自动合并它。
要对表空间进行“碎片整理”,您需要将这些段移动到数据文件的开头而不是末尾。对于桌子,这是一个离线过程,这意味着在移动进行时桌子将不可用。索引可以离线移动,也可以使用企业版移动到在线。由于您有一个中断窗口,我建议您按照以下步骤操作。
A.使用超出高水位线的可用空间收缩数据文件。这可以按如下方式完成(查询类似于 Frosty Z 的过程):
SELECT ceil( blocks*(a.BlockSize)/1024/1024) "Current Size",
ceil( (nvl(hwm,1)*(a.BlockSize))/1024/1024 ) "Smallest Poss.",
ceil( blocks*(a.BlockSize)/1024/1024) -
ceil( (nvl(hwm,1)*(a.BlockSize))/1024/1024 ) "Savings",
'alter database datafile '''|| file_name || ''' resize ' ||
ceil((nvl(hwm,1)*(a.BlockSize))/1024/1024/100)*100 || 'm;' "Command"
FROM (SELECT a.*, p.value BlockSize FROM dba_data_files a
JOIN v$parameter p ON p.Name='db_block_size') a
LEFT JOIN (SELECT file_id, max(block_id+blocks-1) hwm FROM dba_extents GROUP BY file_id ) b
ON a.file_id = b.file_id
WHERE ceil( blocks*(a.BlockSize)/1024/1024) - ceil( (nvl(hwm,1)*(a.BlockSize))/1024/1024 )
> 100 /* Minimum MB it must shrink by to be considered. */
ORDER BY "Savings" Desc;
Run Code Online (Sandbox Code Playgroud)
B.在将东西缩小到高水位线以上之后,找出哪些表空间仍然可以从段移动中受益。
SELECT DISTINCT tablespace_name FROM
(
SELECT tablespace_name, block_id + blocks LastBlock,
lead(block_id) OVER (PARTITION BY File_ID
ORDER BY tablespace_name, file_id, block_id) NextBlock
FROM dba_free_space
) WHERE LastBlock <> NextBlock AND NextBlock IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)
C.对于这些表空间中的每一个,确定需要移动哪些段。(将 USERS 替换为您的表空间的名称或将其与之前的查询连接)
SELECT distinct de.segment_name
FROM dba_extents de
JOIN
(
SELECT tablespace_name, file_id, MIN(block_id) LowestFreeBlock
FROM dba_free_space
WHERE tablespace_name = 'USERS'
GROUP BY tablespace_name, file_id
) dfs ON dfs.tablespace_name = de.tablespace_name AND dfs.file_id = de.file_id
WHERE de.tablespace_name = 'USERS'
AND de.block_id > dfs.LowestFreeBlock;
Run Code Online (Sandbox Code Playgroud)
D.移动每个表并重建索引和统计信息。
E.重复步骤 A。
我刚刚构建了这些查询中的大部分,因此您需要在使用前彻底测试它们。我想您可以创建一个过程,EXECUTE IMMEDIATE
用于创建动态运行的实际语句,但由于查询将收到 ORA-08103:移动正在进行时对象不再存在,我认为最好手动控制该过程,即使如果它确实意味着更多的时间/努力。
归档时间: |
|
查看次数: |
38584 次 |
最近记录: |