☰
微观世界的层级之美:深度解析Oracle数据块、区(Extent)与段(Segment)的层级关系
2026/10/12 12:40:18 网站建设 项目流程

微观世界的层级之美:深度解析Oracle数据块、区(Extent)与段(Segment)的层级关系

    • 一、开篇显微镜:Oracle是如何存下一张表的?
    • 二、全景层级图:从表空间到数据块的四层架构
    • 三、核心概念逐层拆解:从底层到顶层
      • 1.数据块(Data Block):Oracle的“原子单位”
      • 2.区(Extent):空间分配的“最小合同单位”
      • 3.段(Segment):数据对象的“物理化身”
    • 四、三层结构的完整关系链:一张EMP表的诞生
      • 场景:创建EMP表并插入数据
    • 五、块、区、段的五大核心区别
    • 六、自动段空间管理(ASSM)与传统管理的区别
      • 1.传统空间管理(Manual Segment Space Management)
      • 2.自动段空间管理(ASSM - Automatic Segment Space Management)
    • 七、常见问题与最佳实践
      • 1.问题一:表空间空间足够,但创建表失败?
      • 2.问题二:表有大量空闲空间,但查询很慢?
      • 3.问题三:如何预估一个表需要多少空间?
    • 八、总结:记住这个“书”的类比就够了

🌺The Begin🌺点点关注,收藏不迷路🌺

⬇ ⬇ 底部 ⬇ ⬇

一、开篇显微镜:Oracle是如何存下一张表的?

当你执行CREATE TABLE emp (...)时,Oracle并不是简单地把数据丢进一个文件里,而是按照一套极其精密的“三层存储结构”,将数据层层封装,最终落盘到数据文件中。

这套三层结构就是:

段(Segment)→ 区(Extent)→ 块(Block)

如果说表空间是“书架”,数据文件是“书架的隔层”,那么段就是“一本书”,区是“一章”,块是“一页纸”。今天这篇文章,带你从“一本书”的视角,彻底拆解Oracle存储结构的微观世界。


二、全景层级图:从表空间到数据块的四层架构

先通过一张架构图,看清表空间、段、区、块之间的完整层级关系:

物理映射

逻辑存储结构

数据库 Database

表空间 SYSTEM

表空间 USERS

段 Segment-EMP表

段 Segment-EMP_ID_IDX索引

区 Extent 1-8个连续块

区 Extent 2-8个连续块

区 Extent 3-128个连续块

区 Extent N...

区 Extent 1

区 Extent 2

块 Block 1-8KB

块 Block 2-8KB

块 Block 3-8KB

块 Block ...

数据文件 users01.dbf

数据文件 users02.dbf

关键解读:

  • 蓝色(数据库):顶层容器,一切的开端。
  • 橘色(表空间):逻辑分区,段的家园。
  • 红色(段):数据对象的空间占用实体。
  • 绿色(区):段分配空间的最小单位。
  • 紫色(块):Oracle I/O的最小单位。

三、核心概念逐层拆解:从底层到顶层

1.数据块(Data Block):Oracle的“原子单位”

精确描述:
数据块是Oracle数据库中最小的存储单位和I/O单位。无论你查询一行数据还是百万行数据,Oracle都是从磁盘读取整个块到内存,不会只读一行。

数据块的核心参数:

参数说明典型值
块大小(DB_BLOCK_SIZE)标准块大小,数据库创建时指定8KB(OLTP)/ 32KB(OLAP)
块头(Block Header)存储块地址、块类型、事务信息约100字节
表目录(Table Directory)存储该块中有数据的表的信息动态变化
行目录(Row Directory)存储该块中每行的偏移地址动态变化
空闲空间(Free Space)可用于插入新行或更新行动态变化
行数据(Row Data)实际存储的表行数据数据的主体

数据块的空间管理参数:

-- 查看数据库块大小SHOWPARAMETER db_block_size;-- 查看表的块空间使用情况SELECTtable_name,blocks,empty_blocks,avg_spaceFROMdba_tablesWHEREtable_name='EMP';

PCTFREE与PCTUSED:控制块空间使用的两个关键参数

  • PCTFREE:预留的空间百分比,用于行更新时扩展。默认10%。
  • PCTUSED:块使用率低于此值时,重新允许插入。默认40%。

块是Oracle一切操作的基础,锁的最小粒度是行,但读的最小粒度是块。


2.区(Extent):空间分配的“最小合同单位”

精确描述:
区是Oracle为段分配空间的最小单位,由连续的数据块组成。当一个段需要更多空间时,Oracle不会逐个块地分配,而是按区分配,一次给一组连续的块。

区的核心特征:

  1. 连续性:区内的所有块在数据文件中是物理连续的。
  2. 大小可变:区的初始大小和后续大小可以不同。
  3. 按需增长:段空间用完时,自动分配新区。

区的分配策略:

-- 创建表时指定区的分配策略CREATETABLEemp(emp_id NUMBER,name VARCHAR2(100))STORAGE(INITIAL64K-- 初始区大小NEXT64K-- 下一个区大小MINEXTENTS1-- 最少区数MAXEXTENTS100-- 最多区数PCTINCREASE0-- 区大小增长率);

查看对象的区分配情况:

-- 查看EMP表的区分配SELECTextent_id,file_id,block_id,blocks,bytes/1024ASsize_kbFROMdba_extentsWHEREsegment_name='EMP'ANDowner='SCOTT'ORDERBYextent_id;

区的分配示例:

区编号起始块块数大小何时分配
Extent 0Block 100864KB创建表时
Extent 1Block 256864KB前8个块用完后
Extent 2Block 5121281MB数据量增大后

区是Oracle管理空间分配的“批处理”机制,减少了逐个块分配的开销。


3.段(Segment):数据对象的“物理化身”

精确描述:
段是Oracle中占用存储空间的数据库对象。每一个有实际数据的表、索引、物化视图、簇等,都对应一个段。段是区的集合,区是块的集合。

段的核心特征:

  1. 对象级实体:一个表 = 一个段,一个索引 = 一个段。
  2. 空间持有者:段是真正占用数据文件空间的实体。
  3. 不可跨表空间:一个段的所有区必须在同一个表空间内。

常见段类型:

序号段类型对应对象说明
1TABLE普通表、分区表存放表的数据行
2INDEXB树索引、位图索引存放索引的键值和ROWID
3UNDO回滚段存放修改前的旧值,用于回滚和读一致性
4TEMPORARY临时段排序、哈希连接产生的临时空间
5LOB大对象列存放CLOB、BLOB的大数据

查看段信息:

-- 查看SCOTT用户下所有段SELECTsegment_name,segment_type,tablespace_name,blocks,bytes/1024/1024ASsize_mbFROMdba_segmentsWHEREowner='SCOTT'ORDERBYbytesDESC;

四、三层结构的完整关系链:一张EMP表的诞生

让我们通过一个完整的实例,追踪一张表从创建到数据增长,是如何使用三层存储结构的:

场景:创建EMP表并插入数据

步骤一:创建表(生成段)

CREATETABLEemp(emp_id NUMBERPRIMARYKEY,name VARCHAR2(100),salary NUMBER)TABLESPACEusers;

发生了什么:

  • 在USERS表空间中创建一个名为EMP的段(SEGMENT)。
  • 段类型为TABLE。
  • 分配第一个区(Extent 0),包含8个连续块(每个8KB)。
  • 此时段总大小 = 64KB。

步骤二:插入少量数据(使用第一个区)

INSERTINTOempVALUES(1,'张三',5000);INSERTINTOempVALUES(2,'李四',6000);

发生了什么:

  • 数据写入Extent 0的第一个块(Block 1)。
  • 每个块8KB,一行数据约100字节,一个块可存约80行。
  • 此时段仍只占用1个区,64KB。

步骤三:大量插入数据(触发新区分配)

-- 插入10万行数据BEGINFORiIN1..100000LOOPINSERTINTOempVALUES(i,'员工'||i,5000+i);ENDLOOP;COMMIT;END;

发生了什么:

  1. Extent 0的8个块很快被填满。
  2. Oracle自动分配Extent 1(又8个块,64KB)。
  3. 数据继续增长,分配Extent 2(可能升级到128个块,1MB)。
  4. 随着数据量增大,后续区的块数越来越多。
  5. EMP段现在由多个区组成,每个区由连续块组成。

步骤四:创建索引(生成另一个段)

CREATEINDEXidx_emp_nameONemp(name)TABLESPACEusers;

发生了什么:

  • 在USERS表空间中创建另一个名为IDX_EMP_NAME的段(SEGMENT)。
  • 段类型为INDEX。
  • 这个段也有自己的区链和块链。
  • EMP表和IDX_EMP_NAME索引是两个独立的段,各自管理空间。

五、块、区、段的五大核心区别

序号对比维度数据块(Block)区(Extent)段(Segment)
1层级定位最底层,原子单位中间层,空间分配单位最顶层,数据对象实体
2大小固定(通常8KB)可变(64KB~几百MB)可变(几KB~几TB)
3连续性单个块不涉及连续区内所有块必须连续段内各区可以不连续
4对应关系1个区 = N个连续块1个段 = N个不连续的区1个对象 = 1个段(通常)
5分配时机写入数据时使用段空间不足时按需分配创建对象时立即分配第一个区

六、自动段空间管理(ASSM)与传统管理的区别

1.传统空间管理(Manual Segment Space Management)

特征:

  • 使用PCTFREE、PCTUSED、FREELISTS参数手动管理。
  • 通过空闲列表(Freelist)跟踪可用的块。
  • 高并发插入时,Freelist争用成为性能瓶颈。

2.自动段空间管理(ASSM - Automatic Segment Space Management)

特征:

  • 使用位图(Bitmap)跟踪块的使用状态。
  • 无需PCTUSED、FREELISTS参数。
  • 并发插入性能大幅提升,是Oracle 10g后的默认方式。

创建ASSM表空间:

CREATETABLESPACEassm_tbs DATAFILE'/u01/oradata/ORCL/assm_tbs01.dbf'SIZE100M EXTENT MANAGEMENTLOCALAUTOALLOCATE SEGMENT SPACE MANAGEMENT AUTO;-- 关键:AUTO表示使用ASSM

查看表空间是否使用ASSM:

SELECTtablespace_name,segment_space_managementFROMdba_tablespaces;

七、常见问题与最佳实践

1.问题一:表空间空间足够,但创建表失败?

原因:段的第一个区无法分配足够的连续块。

解决:整理表空间碎片,合并空闲空间。

-- 合并空闲空间ALTERTABLESPACEusersCOALESCE;-- 查看表空间的碎片情况SELECTtablespace_name,COUNT(*)ASfragments,SUM(bytes)/1024/1024ASfree_mbFROMdba_free_spaceGROUPBYtablespace_name;

2.问题二:表有大量空闲空间,但查询很慢?

原因:大量DELETE操作导致块内碎片,高水位线未下降。

解决:重组表,降低高水位线。

-- 方式一:移动表ALTERTABLEemp MOVE;-- 方式二:收缩表(Oracle 10g+)ALTERTABLEempENABLEROWMOVEMENT;ALTERTABLEemp SHRINK SPACECASCADE;-- 重建索引(MOVE后索引失效)ALTERINDEXidx_emp_name REBUILD;

3.问题三:如何预估一个表需要多少空间?

估算公式:

表占用空间 = 行数 × 平均行长度 × (1 + PCTFREE/100) 段占用空间 = 表占用空间 + 索引占用空间 所需块数 = CEIL(段占用空间 / (块大小 × 可用空间比例)) 所需区数 = 根据区的分配策略动态分配
-- 查看表的平均行长SELECTtable_name,avg_row_len,num_rows,blocksFROMdba_tablesWHEREtable_name='EMP';

八、总结:记住这个“书”的类比就够了

【段是一本书,区是一章,块是一页】

  • 段(Segment)- 一本书:一个表就是一本完整的书,包含所有内容。
  • 区(Extent)- 一章:书的内容分章节,每一章由连续的页码组成。
  • 块(Block)- 一页:每一页有固定大小,是阅读和翻页的最小单位。

当书的内容增多(插入数据),作者会申请新的纸张(分配新区)。每张纸可以写固定字数的内容(每个块可存固定数量的行)。如果书的内容被大量删除(DELETE),纸张会出现空白(碎片),需要通过收缩(SHRINK)来释放多余的纸张。

理解了段、区、块的三层结构,你就掌握了Oracle存储管理的微观世界。下次当有人问你“表空间里到底存了什么”,你可以自信地回答:表空间存的是段,段由区组成,区由块组成,块里面才是真正的一行行数据。

你在日常运维中,是否遇到过因为段碎片导致的空间浪费?或者因为区分配策略不当导致的性能问题?欢迎在评论区分享你的实战经验。



🌺The End🌺点点关注,收藏不迷路🌺

⬆ ⬆ 顶部 ⬆ ⬆

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询