在 Oracle 数据库中,“表”和“段”是两个截然不同的概念,各自承担不同的职责。本文参考《Oracle 内核技术揭秘》一书的相关内容,进行相关实验,
表与段的定义
- 表:表从逻辑上说明表的形式,比如表有几列,每列的类型、长度。
- 段:段代表实际存储数据的空间。段由一个或多个“区(Extent)”组成,用于为表的数据分配存储空间。
表与段的 ID
Oracle中,每个对象都有一个ID值,表有表的ID,段有段的ID。
- 表 ID(OBJECT_ID):在
DBA_OBJECTS
视图的OBJECT_ID
列中显示,创建表时即被分配,且在表的生命周期内通常不变。 - 段 ID(DATA_OBJECT_ID):在
DBA_OBJECTS
视图的DATA_OBJECT_ID
列中显示,表示与该表关联的段的标识。
实验示例
1. 创建测试表并查看初始 ID
create table test as select * from dba_objects where 1=2;select object_name, object_id, data_object_id from dba_objects where object_name='TEST';
输出结果:
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
------------ ---------- --------------
TEST 73632 73632
表的 ID 和段的 ID 初始时一致
2. 插入数据后,段的大小变化
插入数据后,段会分配存储空间:
insert into test select * from dba_objects;
commit;select sum(bytes)/1024/1024 MB from dba_extents where segment_name='TEST';
输出结果:
MB
----------11
在 DBA_SEGMENTS
视图中同样可以查询段的大小:
select bytes/1024/1024 MB from dba_segments where segment_name='TEST';
输出结果:
MB
----------11
3. 删除数据后段大小的观察
delete from test;select bytes/1024/1024 MB from dba_segments where segment_name='TEST';
输出结果:
MB
----------11
结论:执行 DELETE
操作仅删除表中的数据,但并不会释放段所占用的存储空间。
参考:Oracle delete删除数据是否为逻辑删除、新插入数据占用的数据块位置实验 - 墨天轮
4. 使用 TRUNCATE 清空表
truncate table test;select bytes/1024/1024 MB from dba_segments where segment_name='TEST';
输出结果:
MB
----------0.0625
结论:TRUNCATE
操作会彻底清空表的数据,并释放大部分存储空间(保留部分最小存储单元)。
此外,TRUNCATE
操作会导致 DATA_OBJECT_ID 发生变化:
select object_name, object_id, data_object_id from dba_objects where object_name='TEST';
输出结果:
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
------------ ---------- --------------
TEST 73632 73633
分析:
- 表的 OBJECT_ID 不变。
- 段的 DATA_OBJECT_ID 增加了 1,这是因为
TRUNCATE
删除了原段,并重新分配了一个新段。
多次 TRUNCATE 的规律
反复进行数据插入、提交和 TRUNCATE
操作,观察结果:
TRUNCATE 前:
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
------------ ---------- --------------
TEST 73632 73633TRUNCATE 后:
OBJECT_NAME OBJECT_ID DATA_OBJECT_ID
------------ ---------- --------------
TEST 73632 73634
每次 TRUNCATE
后,OBJECT_ID 保持不变,而 DATA_OBJECT_ID 会递增。
结论
- 表的 ID(OBJECT_ID)在其生命周期内不会改变。
- 段的 ID(DATA_OBJECT_ID)随着段的重新分配而变化。每次
TRUNCATE
表时,Oracle 会删除原有段并重新分配新的段,导致 DATA_OBJECT_ID 增加。 - 使用
DELETE
删除数据并不会释放段所占用的存储空间;而TRUNCATE
操作不仅清空数据,还会释放空间并重新分配最小段。 - 在实际使用中,
TRUNCATE
比DELETE
高效,但需要注意其会影响段的存储逻辑(如重置高水位线、重建段)。