首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Oracle 23ai | DBMS_SPACE 支持收缩小文件表空间

Oracle 23ai | DBMS_SPACE 支持收缩小文件表空间

作者头像
Yunjie Ge
发布2025-11-17 18:24:26
发布2025-11-17 18:24:26
1060
举报
文章被收录于专栏:数据库与编程数据库与编程
在 Oracle 数据库 23ai 版本中,空间管理能力迎来了又一次提升。 从该版本开始,我们不仅可以通过 DBMS_SPACE 包对 大文件表空间(Bigfile Tablespace)进行收缩以回收未使用空间,还能在 23.7 版本之后,对小文件表空间(Smallfile Tablespace)执行同样的空间回收操作。

这意味着数据库管理员在面对长期运行、频繁删除或重建表数据的环境中,能更灵活、更高效地优化存储资源。

一、功能背景

在数据库长时间运行过程中,随着表、索引的反复创建与删除,数据文件中会产生大量未使用的“空洞”。 这些空间虽然被标记为空闲,但在物理层面上仍然占用磁盘。 而过去,Oracle 提供的表空间收缩能力主要集中在 大文件表空间,对于小文件表空间的空间回收并不支持。

Oracle 23ai 23.7 起,DBMS_SPACE 包的 SHRINK_TABLESPACE 过程新增了对小文件表空间的支持,使得我们可以更精细地管理多数据文件表空间的空间使用情况。

二、准备测试环境

下面我们通过一个完整的实验演示来验证这一新特性。 实验环境为 Oracle 23ai(23.7 版本及以上),连接方式如下:

代码语言:javascript
复制
conn sys/Oracle1@//localhost:1521/pdb1 as sysdba

1. 创建小文件表空间

在 Oracle 23ai 中,默认创建的是大文件表空间(bigfile)。 因此我们在测试时,需要显式指定创建 smallfile 表空间,并包含多个数据文件。

代码语言:javascript
复制
-- 创建一个包含多个数据文件的表空间
drop user if exists test_user cascade;
drop tablespace if exists test_ts including contents and datafiles;
create smallfile tablespace test_ts datafile
  size 10m autoextend on next 1m,
  size 10m autoextend on next 1m,
  size 10m autoextend on next 1m,
  size 10m autoextend on next 1m;

2. 创建测试用户及授权

代码语言:javascript
复制
-- 创建测试用户并授权
drop user if exists test_user cascade;
create user test_user identified by test_user default tablespace test_ts quota unlimited on test_ts;
grant create session, create table to test_user;
grant select_catalog_role to test_user;

3. 创建测试表并插入数据

我们在测试用户下创建两张表 t1t2,插入大量数据以模拟真实使用场景:

代码语言:javascript
复制
-- 在测试用户下创建两张表并插入测试数据
conn test_user/test_user@//localhost:1521/pdb1
create table t1 (
  id   number,
  col1 varchar2(4000),
  col2 varchar2(4000),
  constraint t1_pk primary key (id)
);
create table t2 (
  id   number,
  col1 varchar2(4000),
  col2 varchar2(4000),
  constraint t2_pk primary key (id)
);
insert /*+append*/ into t1
select rownum, rpad('x', 4000, 'x'), rpad('x', 4000, 'x')
from dual
connect by level <= 100000;
commit;
insert /*+append*/ into t2
select rownum, rpad('x', 4000, 'x'), rpad('x', 4000, 'x')
from dual
connect by level <= 100000;
commit;
exec dbms_stats.gather_table_stats(null, 't1');
exec dbms_stats.gather_table_stats(null, 't2');

三、查看空间使用情况

我们先查看表空间的数据文件大小及每张表的占用情况:

代码语言:javascript
复制
column file_name format a30
select substr(file_name, -28) as file_name, blocks, bytes/1024/1024 as size_mb
from   dba_data_files
where  tablespace_name = 'TEST_TS';
FILE_NAME                          BLOCKS    SIZE_MB
------------------------------ ---------- ----------
o1_mf_test__mtmskcv6_.dbf       124928        976
o1_mf_test__mtmskcvd_.dbf       109312        854
o1_mf_test__mtmskcvl_.dbf        98048        766
o1_mf_test__mtmskcvr_.dbf        98944        773
SQL>
column table_name format a10
select table_name, blocks, (blocks*8)/1024 as size_mb
from   user_tables
where  table_name in ('T1', 'T2')
order by 1;
TABLE_NAME     BLOCKS    SIZE_MB
---------- ---------- ----------
T1             200692 1567.90625
T2             200692 1567.90625

执行后可看到每个数据文件和表对象的空间占用情况。 此时表空间已被两张大表占满。

四、释放空间并分析收缩潜力

我们清空表 t1,使其腾出大量未使用空间。

代码语言:javascript
复制
truncate table t1;
exec dbms_stats.gather_table_stats(null, 't1');

接着运行分析模式的收缩操作,查看通过 DBMS_SPACE 可回收的空间量:

代码语言:javascript
复制
conn sys/Oracle1@//localhost:1521/pdb1 as sysdba
set serveroutput on
execute dbms_space.shrink_tablespace('TEST_TS', shrink_mode => dbms_space.ts_mode_analyze);

输出结果如下:

代码语言:javascript
复制
-------------------ANALYZE RESULT-------------------
Total Movable Objects: 2
Total Movable Size(GB): .37
Original Datafile Size(GB): 3.29
Suggested Target Size(GB): 1.94
Process Time: +00 00:00:02.036832
PL/SQL procedure successfully completed.

这说明系统检测到约 0.37GB 的可移动数据块,表空间理论上可收缩至约 1.94GB。

五、执行收缩操作

执行真正的收缩动作以回收空间:

代码语言:javascript
复制
set serveroutput on
execute dbms_space.shrink_tablespace('TEST_TS');

执行结果:

代码语言:javascript
复制
-------------------SHRINK RESULT-------------------
Total Moved Objects: 2
Total Moved Size(GB): .37
Original Datafile Size(GB): 3.29
New Datafile Size(GB): 2.76
Process Time: +00 00:00:52.268145
PL/SQL procedure successfully completed.

可见在第一次执行后,表空间成功回收了部分空间。

六、多次收缩以进一步合并文件

我们可以继续执行收缩操作,多次运行以进一步压缩和合并数据文件:

代码语言:javascript
复制
set serveroutput on
execute dbms_space.shrink_tablespace('TEST_TS', shrink_mode => dbms_space.ts_mode_shrink, target_size => dbms_space.ts_target_max_shrink);

多次执行后,可观察到数据文件数量逐渐减少,最终压缩为一个数据文件:

代码语言:javascript
复制
column file_name format a30
select substr(file_name, -28) as file_name, blocks, bytes/1024/1024 as size_mb
from   dba_data_files
where  tablespace_name = 'TEST_TS';
FILE_NAME                          BLOCKS    SIZE_MB
------------------------------ ---------- ----------
o1_mf_test__mtmskcv6_.dbf       382080       2985
SQL>

七、测试结论与经验总结

  1. 小文件表空间收缩大文件表空间收缩 的目标不同。
    • 大文件表空间更关注空间的释放(物理文件缩小)。
    • 小文件表空间则偏向于对象移动和文件合并,以减少碎片。
  2. 即使最终只有一个数据文件,整体节省的空间也可能有限。 这是因为数据段之间的空间利用率与对象分布有关。
  3. 收缩过程中,系统会智能判断哪些对象可以在线移动。 在分析阶段会列出不受支持的对象,若指定 TS_MODE_SHRINK_FORCE,这些对象将离线移动。 若业务对可用性要求高,请谨慎使用该模式。
  4. 对于未启用自动扩展的表空间,收缩完成后可能没有足够的空间供新段扩张。 管理员需手动调整表空间大小以保证后续操作的正常进行。

通过实验,验证了 Oracle 23ai (23.7) 新增的小文件表空间收缩能力。 借助 DBMS_SPACE.SHRINK_TABLESPACE,数据库管理员可以更灵活地进行空间回收与优化,减少存储浪费,提高数据文件管理的可控性。

在生产环境中,这一功能对于包含多个数据文件、频繁删除数据或历史归档的场景尤其有价值。 合理使用此特性,能有效降低存储成本,保持数据库空间结构的健康与整洁。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 山东Oracle用户组 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、功能背景
  • 二、准备测试环境
    • 1. 创建小文件表空间
    • 3. 创建测试表并插入数据
  • 三、查看空间使用情况
  • 四、释放空间并分析收缩潜力
  • 五、执行收缩操作
  • 六、多次收缩以进一步合并文件
  • 七、测试结论与经验总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档