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 | 索引分区 | 分区名 |
| LOBSEGMENT | LOB 数据段 | 表名 + 列名 |
| LOB PARTITION | LOB 分区 | 分区名 |
| LOBINDEX | LOB 索引 | SYS_IL… |
| ROLLBACK | 回滚段(旧版) | SYSTEM |
| TYPE2 UNDO | Undo 段 | _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 Index | 1 个 INDEX 段 |
| Bitmap Index | 1 个 INDEX 段 |
| 分区索引 | 多个 INDEX PARTITION 段 |
| Function-Based Index | 1 个 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 数据 |
| LOBINDEX | LOB 索引(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 大小策略
| 策略 | 说明 |
|---|---|
| AUTOALLOCATE | Oracle 自动选择(推荐) |
| 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. 最佳实践
- 业务表用 ASSM:自动段空间管理
- 大表用分区:便于管理
- LOB 用 SECUREFILE:高级特性
- 定期监控段大小:避免单个段过大
- 使用 Segment Advisor:识别可收缩的段
- TRUNCATE 释放空间:替代 DELETE
- 历史数据归档:使用分区交换
- 合理设置 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