Oracle 段(Segment)类型与分配

Oracle 段(Segment)类型与分配

适用版本:Oracle Database 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

段(Segment) 是 Oracle 中占用存储空间的对象,由若干区(Extent)组成[1]:

Database
  └── Tablespace
        └── Segment(段)
              └── Extent(区,连续数据块)
                    └── Data Block(数据块)

2. 段类型

2.1 主要段类型

类型说明段名
TABLE普通表表名
INDEX索引索引名
CLUSTER簇名
TABLE PARTITION表分区分区名
INDEX PARTITION索引分区分区名
LOBSEGMENTLOB 数据段表名 + 列名
LOB PARTITIONLOB 分区分区名
LOBINDEXLOB 索引SYS_IL…
ROLLBACK回滚段(旧版)SYSTEM
TYPE2 UNDOUndo 段_SYSSMU…
TEMPORARY临时段SYS_TEMP…
CACHE缓存段-
NESTED TABLE嵌套表表名

2.2 查看段类型

-- 所有段类型统计
SELECT segment_type, COUNT(*) AS cnt, SUM(bytes)/1024/1024 AS mb
FROM dba_segments
GROUP BY segment_type
ORDER BY mb DESC;

-- 大段 Top 20
SELECT 
  owner,
  segment_name,
  segment_type,
  tablespace_name,
  bytes/1024/1024 AS mb,
  extents,
  blocks
FROM dba_segments
ORDER BY bytes DESC
FETCH FIRST 20 ROWS ONLY;

3. 表段(TABLE)

3.1 普通表

CREATE TABLE employees (
  id NUMBER PRIMARY KEY,
  name VARCHAR2(100),
  salary NUMBER
) TABLESPACE users;
-- 创建一个 TABLE 类型段

3.2 分区表

CREATE TABLE sales (
  sale_id NUMBER,
  sale_date DATE,
  amount NUMBER
)
PARTITION BY RANGE (sale_date) (
  PARTITION p_2025_q1 VALUES LESS THAN (TO_DATE('2025-04-01','YYYY-MM-DD')),
  PARTITION p_2025_q2 VALUES LESS THAN (TO_DATE('2025-07-01','YYYY-MM-DD'))
);
-- 每个分区是一个独立的 TABLE PARTITION 段

3.3 索引组织表(IOT)

CREATE TABLE iot_emp (
  id NUMBER PRIMARY KEY,
  name VARCHAR2(100)
) ORGANIZATION INDEX;
-- 数据存储在索引中,无独立表段

3.4 簇表

CREATE CLUSTER emp_dept (dept_id NUMBER(10));

CREATE TABLE dept (
  dept_id NUMBER PRIMARY KEY,
  dname VARCHAR2(30)
) CLUSTER emp_dept(dept_id);

CREATE TABLE emp (
  emp_id NUMBER PRIMARY KEY,
  dept_id NUMBER,
  ename VARCHAR2(30)
) CLUSTER emp_dept(dept_id);
-- 多个表共享一个簇段

4. 索引段(INDEX)

4.1 索引类型

类型段数
B-Tree Index1 个 INDEX 段
Bitmap Index1 个 INDEX 段
分区索引多个 INDEX PARTITION 段
Function-Based Index1 个 INDEX 段
Domain Index多个段

4.2 创建索引

-- 普通 B-Tree
CREATE INDEX idx_emp_name ON employees(name) TABLESPACE users;

-- 位图索引(OLAP 场景)
CREATE BITMAP INDEX idx_emp_dept ON employees(dept_id);

-- 函数索引
CREATE INDEX idx_emp_upper ON employees(UPPER(name));

-- 分区索引
CREATE INDEX idx_sales_date ON sales(sale_date) 
  LOCAL (
    PARTITION p_2025_q1,
    PARTITION p_2025_q2
  );

5. LOB 段

5.1 LOB 存储

CREATE TABLE docs (
  id NUMBER,
  content CLOB,
  data BLOB
) LOB (content) STORE AS SECUREFILE (
  ENABLE STORAGE IN ROW
  DEDUPLICATE
  COMPRESS HIGH
);

5.2 LOB 相关段

每个 LOB 列生成:

作用
LOBSEGMENT存储实际 LOB 数据
LOBINDEXLOB 索引(B-Tree)
-- 查看 LOB 段
SELECT 
  table_name,
  column_name,
  segment_name,
  index_name
FROM dba_lobs
WHERE owner = USER;

6. Undo 段

6.1 自动 Undo 管理

SHOW PARAMETER undo_management;
-- AUTO(推荐)

-- Undo 段自动创建
SELECT segment_name, tablespace_name, status 
FROM dba_rollback_segs;
-- 自动创建:_SYSSMU1$, _SYSSMU2$, ...

6.2 查看活动事务

SELECT 
  addr, xidusn, xidslot, xidsqn,
  status, start_time, used_ublk
FROM v$transaction;

7. 临时段

7.1 用途

  • 排序溢出
  • 哈希连接
  • 临时表
  • 索引创建

7.2 临时表

-- 全局临时表
CREATE GLOBAL TEMPORARY TABLE temp_emp (
  id NUMBER,
  name VARCHAR2(100)
) ON COMMIT PRESERVE ROWS;

-- 会话级临时表(18c+)
CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp AS
  SELECT * FROM employees WHERE 1=0;

8. 段空间管理

8.1 EXTENT 分配

-- 查看段的 extent 分配
SELECT 
  segment_name,
  segment_type,
  extent_id,
  file_id,
  block_id,
  bytes/1024/1024 AS mb
FROM dba_extents
WHERE owner = USER
  AND segment_name = 'EMPLOYEES'
ORDER BY extent_id;

8.2 段空间管理方式

方式表空间参数
ASSM(自动段空间管理)SEGMENT SPACE MANAGEMENT AUTO
MSSM(手动)SEGMENT SPACE MANAGEMENT MANUAL
-- 查看
SELECT 
  tablespace_name, 
  extent_management, 
  segment_space_management
FROM dba_tablespaces;

8.3 EXTENT 大小策略

策略说明
AUTOALLOCATEOracle 自动选择(推荐)
UNIFORM SIZE所有 extent 相同大小
-- 自动分配
CREATE TABLESPACE ts_auto 
  DATAFILE '/u01/ts_auto.dbf' SIZE 1G
  EXTENT MANAGEMENT LOCAL AUTOALLOCATE;

-- 统一大小
CREATE TABLESPACE ts_uniform 
  DATAFILE '/u01/ts_uniform.dbf' SIZE 1G
  EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;

9. 相关视图

-- 段总览
SELECT 
  owner,
  segment_name,
  segment_type,
  tablespace_name,
  bytes/1024/1024 AS mb,
  extents,
  blocks
FROM dba_segments
WHERE owner = USER
ORDER BY bytes DESC;

-- 段空间顾问建议
SELECT 
  segment_owner,
  segment_name,
  segment_type,
  partition_name,
  recommendation,
  c1 AS space_save_mb
FROM dba_segment_advisor_recommendations
FETCH FIRST 20 ROWS ONLY;

10. 常见坑与排错

10.1 段过大

现象:单个段超过 100GB。

修复

  • 使用分区表
  • 归档历史数据
  • 启用表压缩

10.2 段碎片化

现象:DELETE 后段空间未释放。

修复

-- SHRINK SPACE
ALTER TABLE large_tab ENABLE ROW MOVEMENT;
ALTER TABLE large_tab SHRINK SPACE;

-- 或 MOVE
ALTER TABLE large_tab MOVE;

10.3 LOB 段未启用 SECUREFILE

-- 检查
SELECT table_name, column_name, storage_type
FROM dba_lobs
WHERE owner = USER;

-- 转换为 SECUREFILE
ALTER TABLE docs MOVE 
  LOB (content) STORE AS SECUREFILE (COMPRESS HIGH);

11. 最佳实践

  1. 业务表用 ASSM:自动段空间管理
  2. 大表用分区:便于管理
  3. LOB 用 SECUREFILE:高级特性
  4. 定期监控段大小:避免单个段过大
  5. 使用 Segment Advisor:识别可收缩的段
  6. TRUNCATE 释放空间:替代 DELETE
  7. 历史数据归档:使用分区交换
  8. 合理设置 EXTENT 大小:AUTOALLOCATE 推荐

12. 参考资料

[1] Oracle Database Concepts 19c, “Logical Storage Structures” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/logical-storage-structures.html

[2] Oracle Database Administrator’s Guide 19c, “Managing Segments” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/managing-segments.html