Oracle查看对象空间使用情况show_space

本文介绍了一个由Tom大神撰写的Oracle数据库工具,用于查看特定对象的空间使用情况,包括总块数、总字节数、未使用的块数、最后使用的扩展文件ID等信息。通过演示代码及实例,展示了如何利用该工具获取数据库对象的空间利用率。

tom大神写了一个用于查看Oracle数据库对象空间使用情况。
下面演示一下如何使用:

–工具源码

CREATE OR REPLACE PROCEDURE show_space(p_segname   IN VARCHAR2,
                                       p_owner     IN VARCHAR2 DEFAULT USER,
                                       p_type      IN VARCHAR2 DEFAULT 'TABLE',
                                       p_partition IN VARCHAR2 DEFAULT NULL) AS
  l_free_blks          NUMBER;
  l_total_blocks       NUMBER;
  l_total_bytes        NUMBER;
  l_unused_blocks      NUMBER;
  l_unused_bytes       NUMBER;
  l_lastusedextfileid  NUMBER;
  l_lastusedextblockid NUMBER;
  l_last_used_block    NUMBER;
  l_segment_space_mgmt VARCHAR2(255);
  l_unformatted_blocks NUMBER;
  l_unformatted_bytes  NUMBER;
  l_fs1_blocks         NUMBER;
  l_fs1_bytes          NUMBER;
  l_fs2_blocks         NUMBER;
  l_fs2_bytes          NUMBER;
  l_fs3_blocks         NUMBER;
  l_fs3_bytes          NUMBER;
  l_fs4_blocks         NUMBER;
  l_fs4_bytes          NUMBER;
  l_full_blocks        NUMBER;
  l_full_bytes         NUMBER;

  PROCEDURE p(p_label IN VARCHAR2,
              p_num   IN NUMBER) IS
  BEGIN
    dbms_output.put_line(rpad(p_label, 40, '.') ||
                         to_char(p_num, '999,999,999,999'));
  END;
BEGIN
  EXECUTE IMMEDIATE 'select ts.segment_space_management from dba_segments seg,dba_tablespaces ts where seg.segment_name = :p_segname and (:p_partition is null or seg.partition_name = :p_partition) and seg.owner = :p_owner and seg.tablespace_name=ts.tablespace_name'
    INTO l_segment_space_mgmt
    USING p_segname, p_partition, p_partition, p_owner;

  --     exception
  --             when too_many_rows
  --             then
  --             dbms_output.put_line('This must be a partitioned table,use p_partition => ');
  --             return;
  --     end;

  IF l_segment_space_mgmt = 'AUTO' THEN
    dbms_space.space_usage(p_owner, p_segname, p_type, l_unformatted_blocks,
                           l_unformatted_bytes, l_fs1_blocks, l_fs1_bytes,
                           l_fs2_blocks, l_fs2_bytes, l_fs3_blocks, l_fs3_bytes,
                           l_fs4_blocks, l_fs4_bytes, l_full_blocks,
                           l_full_bytes, p_partition);

    p('Unformatted Blocks  ', l_unformatted_blocks);
    p('FS1 Blocks (0-25)   ', l_fs1_blocks);
    p('FS2 Blocks (25-50)  ', l_fs2_blocks);
    p('FS3 Blocks (50-75)  ', l_fs3_blocks);
    p('FS4 Blocks (75-100) ', l_fs4_blocks);
    p('Full Blocks         ', l_full_blocks);
  ELSE
    dbms_space.free_blocks(segment_owner => p_owner, segment_name => p_segname,
                           segment_type => p_type, freelist_group_id => 0,
                           free_blks => l_free_blks);
  END IF;

  dbms_space.unused_space(segment_owner => p_owner, segment_name => p_segname,
                          segment_type => p_type, partition_name => p_partition,
                          total_blocks => l_total_blocks,
                          total_bytes => l_total_bytes,
                          unused_blocks => l_unused_blocks,
                          unused_bytes => l_unused_bytes,
                          last_used_extent_file_id => l_lastusedextfileid,
                          last_used_extent_block_id => l_lastusedextblockid,
                          last_used_block => l_last_used_block);

  p('Total Blocks ', l_total_blocks);
  p('Total Bytes  ', l_total_bytes);    
  p('Total MBytes ', trunc(l_total_bytes / 1024 / 1024));
  p('Unused Blocks', l_unused_blocks);
  p('Unused Bytes ', l_unused_bytes);
  p('Last Used Ext FileId', l_lastusedextfileid);
  p('Last Used Ext BlockId', l_lastusedextblockid);
  p('Last Used Block', l_last_used_block);
END;

–用法演示

create table test_space
AS
select * from dba_tables;
/
SYS@orcl> exec show_space('TEST_SPACE');

Total Blocks ……………………… 112
Total Bytes ……………………… 917,504
Total MBytes ……………………… 0
Unused Blocks……………………… 3
Unused Bytes ……………………… 24,576
Last Used Ext FileId……………….. 1
Last Used Ext BlockId………………. 115,608
Last Used Block……………………. 5

PL/SQL 过程已成功完成。

SYS@orcl> delete from test_space;

已删除3044行。

SYS@orcl> commit;

提交完成。

SYS@orcl> exec show_space('TEST_SPACE');

Total Blocks ……………………… 112
Total Bytes ……………………… 917,504
Total MBytes ……………………… 0
Unused Blocks……………………… 3
Unused Bytes ……………………… 24,576
Last Used Ext FileId……………….. 1
Last Used Ext BlockId………………. 115,608
Last Used Block……………………. 5

PL/SQL 过程已成功完成。

SYS@orcl> truncate table test_space;

表被截断。

SYS@orcl> exec show_space(‘TEST_SPACE’);
Total Blocks ……………………… 8
Total Bytes ……………………… 65,536
Total MBytes ……………………… 0
Unused Blocks……………………… 7
Unused Bytes ……………………… 57,344
Last Used Ext FileId……………….. 1
Last Used Ext BlockId………………. 101,872
Last Used Block……………………. 1

PL/SQL 过程已成功完成。

drop table test_space;
<think>我们有两个需求:1. 查询普通表空间使用率;2. 查询临时表空间使用率。根据引用[2]和引用[3]提供的方法,我们可以分别编写SQL。 注意:引用[2]中提供了普通表空间使用率的查询,引用[3]提供了临时表空间使用率的查询。 普通表空间使用率查询(参考引用[2]并稍作调整): - 使用dba_data_files获取表空间总大小 - 使用dba_free_space获取表空间空闲大小 - 计算已用空间和使用率 临时表空间使用率查询(参考引用[3]): - 使用dba_temp_files获取临时表空间总大小 - 使用v$sort_usage获取临时表空间已用空间 另外,根据用户上一次的问题,我们曾提供了一个查询,这次可以结合引用[2]的写法进行优化(因为引用[2]的写法是常见的连接方式)。 我们将分别提供两个查询,并解释。 同时,注意权限:需要DBA权限。 步骤: 1. 普通表空间使用率查询 2. 临时表空间使用率查询 普通表空间使用率查询SQL(优化写法): ```sql SELECT total.tablespace_name AS "表空间名称", ROUND(total.MB, 2) AS "总容量(MB)", ROUND(total.MB - free.MB, 2) AS "已用空间(MB)", ROUND(free.MB, 2) AS "剩余空间(MB)", ROUND((1 - free.MB / total.MB) * 100, 2) AS "使用率(%)" FROM (SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS MB FROM dba_free_space GROUP BY tablespace_name) free, (SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS MB FROM dba_data_files GROUP BY tablespace_name) total WHERE free.tablespace_name = total.tablespace_name AND total.tablespace_name NOT IN ('SYSTEM','SYSAUX') -- 排除系统表空间 ORDER BY "使用率(%)" DESC; ``` 但是,上述写法可能会遗漏没有空闲空间的表空间(即free中没有记录),所以使用左外连接更安全。另外,引用[2]的写法是内连接,如果某个表空间没有空闲记录(即完全用完),则不会显示剩余空间为0的情况。因此,我们可以使用NVL来避免。 改进:使用左外连接,并处理NULL值。 由于引用[2]的写法可能遗漏,我们采用以下写法(更安全): ```sql SELECT df.tablespace_name AS "表空间名称", ROUND(SUM(df.bytes) / 1024 / 1024, 2) AS "总容量(MB)", ROUND((SUM(df.bytes) - NVL(SUM(fs.bytes), 0)) / 1024 / 1024, 2) AS "已用空间(MB)", ROUND(NVL(SUM(fs.bytes), 0) / 1024 / 1024, 2) AS "剩余空间(MB)", ROUND((SUM(df.bytes) - NVL(SUM(fs.bytes), 0)) * 100 / SUM(df.bytes), 2) AS "使用率(%)" FROM dba_data_files df LEFT JOIN (SELECT tablespace_name, SUM(bytes) AS bytes FROM dba_free_space GROUP BY tablespace_name) fs ON df.tablespace_name = fs.tablespace_name WHERE df.tablespace_name NOT IN ('SYSTEM','SYSAUX') -- 排除系统表空间 GROUP BY df.tablespace_name ORDER BY "使用率(%)" DESC; ``` 临时表空间使用率查询(参考引用[3]): ```sql SELECT D.tablespace_name AS "表空间名称", ROUND(D.space, 2) AS "总容量(MB)", ROUND(F.used_space, 2) AS "已用空间(MB)", ROUND(D.space - F.used_space, 2) AS "剩余空间(MB)", ROUND(Nvl(F.used_space, 0) / D.space * 100, 2) AS "使用率(%)" FROM (SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS space FROM dba_temp_files GROUP BY tablespace_name) D LEFT JOIN (SELECT tablespace, SUM(blocks * (SELECT value FROM v$parameter WHERE name = 'db_block_size') / 1024 / 1024) AS used_space FROM v$sort_usage GROUP BY tablespace) F ON D.tablespace_name = F.tablespace WHERE D.tablespace_name IN ('TEMP', 'TEMP1') -- 这里填写需要查询的临时表空间名称 ORDER BY "使用率(%)" DESC; ``` 注意:在临时表空间查询中,v$sort_usage中的blocks乘以的是每个块的大小(字节数),而块大小可以通过查询v$parameter获取(db_block_size)。但是,引用[3]中直接使用了8192(即8KB),这假设块大小为8K。为了通用性,我们可以动态获取块大小。 但是,由于v$parameter可能没有直接给出每个块的大小,我们可以使用以下方式之一: 1. 使用`SHOW PARAMETER db_block_size;` 获取,但这是在SQL*Plus中,不能在SQL语句中使用。 2. 在SQL中查询v$parameter,如:`(SELECT value FROM v$parameter WHERE name = 'db_block_size')`,但注意,如果多个实例,可能需要考虑。 然而,在临时表空间使用情况查询中,更常见的做法是直接使用8192(因为大部分数据库块大小是8K),但为了准确,我们使用动态获取块大小的方法。 另外,注意:临时表空间可能有多个,所以通过IN条件指定。 但是,如果不知道临时表空间名称,可以先查询dba_temp_files获取所有临时表空间。 我们可以先不指定,然后查询所有临时表空间: ```sql SELECT D.tablespace_name AS "表空间名称", ROUND(D.space, 2) AS "总容量(MB)", ROUND(Nvl(F.used_space, 0), 2) AS "已用空间(MB)", ROUND(D.space - Nvl(F.used_space, 0), 2) AS "剩余空间(MB)", ROUND(Nvl(F.used_space, 0) * 100 / D.space, 2) AS "使用率(%)" FROM (SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS space FROM dba_temp_files GROUP BY tablespace_name) D LEFT JOIN (SELECT tablespace, SUM(blocks * (SELECT value FROM v$parameter WHERE name = 'db_block_size') / 1024 / 1024) AS used_space FROM v$sort_usage GROUP BY tablespace) F ON D.tablespace_name = F.tablespace ORDER BY "使用率(%)" DESC; ``` 但是,注意:v$sort_usage只记录当前正在使用的临时空间,当临时操作结束后,空间会被释放,所以这个使用率是当前使用情况。 根据以上,我们提供两个查询:普通表空间和临时表空间。 另外,引用[1]中提到,当表空间使用率超过90%时,需要采取措施。 下面,我将分别给出两个查询的完整SQL,并附上说明。 注意:如果用户没有DBA权限,可能无法访问这些视图。普通用户可以使用user_或all_开头的视图,但只能查看自己有权限的表空间。 但是,问题要求查看整个数据库的表空间使用率,所以需要DBA权限。 最终回答: 我们将提供两个查询: 1. 普通表空间使用率查询 2. 临时表空间使用率查询 并生成相关问题。</think>### Oracle空间使用率查询方法 以下是查询 Oracle空间使用率的完整解决方案,包含普通表空间和临时表空间的查询方法: #### 1. 普通表空间使用率查询 ```sql SELECT total.tablespace_name AS "表空间名称", ROUND(total.MB, 2) AS "总容量(MB)", ROUND(total.MB - free.MB, 2) AS "已用空间(MB)", ROUND(free.MB, 2) AS "剩余空间(MB)", ROUND((1 - free.MB / total.MB) * 100, 2) || '%' AS "使用率" FROM ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS MB FROM dba_free_space GROUP BY tablespace_name ) free, ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS MB FROM dba_data_files GROUP BY tablespace_name ) total WHERE free.tablespace_name = total.tablespace_name AND total.tablespace_name NOT IN ('SYSTEM','SYSAUX') -- 排除系统表空间 ORDER BY "使用率" DESC; ``` **查询结果示例**: ``` 表空间名称 | 总容量(MB) | 已用空间(MB) | 剩余空间(MB) | 使用率 ----------------------------------------------- USER_DATA | 10240.00 | 9216.00 | 1024.00 | 90.00% INDEX_TS | 5120.00 | 3584.00 | 1536.00 | 70.00% ``` #### 2. 临时表空间使用率查询 ```sql SELECT D.tablespace_name AS "表空间名称", ROUND(D.space, 2) AS "总容量(MB)", ROUND(NVL(F.used_space, 0), 2) AS "已用空间(MB)", ROUND(D.space - NVL(F.used_space, 0), 2) AS "剩余空间(MB)", ROUND(NVL(F.used_space, 0) / D.space * 100, 2) AS "使用率(%)" FROM ( SELECT tablespace_name, SUM(bytes) / (1024 * 1024) AS space FROM dba_temp_files GROUP BY tablespace_name ) D LEFT JOIN ( SELECT tablespace, SUM(blocks * 8192) / (1024 * 1024) AS used_space FROM v$sort_usage GROUP BY tablespace ) F ON D.tablespace_name = F.tablespace; ``` #### 关键视图说明: 1. **`dba_data_files`** 存储所有数据文件信息,包含表空间物理文件大小[^1] 2. **`dba_free_space`** 记录表空间中的空闲空间信息[^2] 3. **`dba_temp_files`** 存储临时表空间文件信息 4. **`v$sort_usage`** 监控临时段使用情况[^3] #### 注意事项: 1. 需要 **DBA 权限** 才能访问系统视图 2. 使用率超过 90% 的表空间需及时处理[^1] 3. 临时表空间使用率反映当前会话的临时段使用情况 4. 系统表空间(SYSTEM/SYSAUX)通常不参与常规监控 5. 块大小默认为 8192 字节(8KB),可根据实际参数调整 > 当表空间使用率接近 100% 时,会导致 "ORA-01653: unable to extend table" 错误,需立即处理[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值