oracle中“不再使用”的段不能仅凭last_ddl_time判断,必须结合v$segstat零访问、dba_hist_seg_stat连续30天无活动及应用侧确认下线三重验证;删前须检查物化视图日志、调度作业依赖和回收站残留,否则易致业务中断或数据字典不一致。
直接查 dba_segments 并删掉“看起来很久没动”的段,大概率会删错甚至导致业务中断——oracle 没有内置字段标记“陈旧”,所谓“陈旧”必须结合访问行为、对象生命周期和空间释放逻辑来交叉判断。
怎么定义“不再使用”的段?别信 LAST_DDL_TIME
很多人用 LAST_DDL_TIME 或 CREATED 判断段是否陈旧,但这是危险的:
- 表可能长期只读,
LAST_DDL_TIME几年不变,但每天被大量查询——删了就断业务 - 索引重建后
LAST_DDL_TIME更新,但原索引段仍被保留(尤其未加DROP OLD) - 分区表中老分区可能
LAST_ANALYZED是 2022 年,但归档策略要求保留 5 年,删了违反合规
真正可操作的“不再使用”信号只有三个:V$SEGSTAT 中长期无逻辑读/物理读、DBA_HIST_SEG_STAT 连续 30 天无活动、且确认该段所属对象已从应用逻辑中下线(非 DBA 能单独判定)。
先筛出高嫌疑段:按空间占用 + 零访问组合过滤
执行以下查询,聚焦真正浪费空间又无访问痕迹的段:
SELECT owner, segment_name, segment_type,
ROUND(bytes/1024/1024/1024, 2) gb,
(SELECT MAX(statistic_name)
FROM v$segment_statistics s
WHERE s.owner = t.owner
AND s.object_name = t.segment_name
AND s.statistic_name IN ('logical reads', 'physical reads')
AND s.value > 0) AS last_access_stat
FROM dba_segments t
WHERE tablespace_name NOT IN ('SYSTEM', 'SYSAUX', 'UNDO', 'TEMP')
AND bytes > 1024*1024*1024 -- 大于 1GB
AND NOT EXISTS (
SELECT 1 FROM v$segment_statistics s
WHERE s.owner = t.owner
AND s.object_name = t.segment_name
AND s.statistic_name IN ('logical reads', 'physical reads')
AND s.value > 0
)
ORDER BY bytes DESC;
注意:v$segment_statistics 只保留最近约 1 小时活跃段数据;如需历史趋势,必须依赖 AWR 快照(DBA_HIST_SEG_STAT),且需确保快照保留期 ≥ 30 天。
删之前必须验证的三件事
跳过任一验证,删段后可能引发隐性故障:
- 检查是否有物化视图日志或 CDC 日志依赖该表:
SELECT * FROM dba_mview_logs WHERE log_table = 'YOUR_TABLE'; - 确认该段未被任何正在运行的作业引用:
SELECT job_name, state, last_start_date FROM dba_scheduler_jobs WHERE job_action LIKE '%<segment_name>%';</segment_name> - 查回收站(
DBA_RECYCLEBIN)里是否已有同名对象——若存在,说明曾被 DROP 过,当前段可能是残留副本,删前先PURGE原回收站条目
特别提醒:DROP TABLE 或 DROP INDEX 后,段不会立刻从 DBA_SEGMENTS 消失,而是转入回收站并标记为 DROPPED 状态;此时直接删物理段会破坏数据字典一致性。
清理后空间不释放?别急着 SHRINK
即使成功删除段,DBA_FREE_SPACE 显示的空闲空间可能不变,原因很具体:
- 临时表空间里的段删完后,需等 SMON 下次轮询(最长 5 分钟)才合并空闲 extent —— 查
V$TEMP_SPACE_HEADER.FREE_BLOCKS才是真实空闲块数 - 普通表空间中,如果段所在文件启用了
AUTOEXTEND,Oracle 不会自动收缩数据文件,dba_data_files.bytes不变是正常现象 - 高水位线(HWM)以下的空闲块,对新插入不可见,必须显式执行
ALTER TABLE ... SHRINK SPACE COMPACT(前提:已开ENABLE ROW MOVEMENT)
最易被忽略的一点:DBA_SEGMENTS.BYTES 统计有延迟,删完段后立即查可能仍显示旧值;等 5 分钟或手动刷新段统计:EXEC DBMS_SPACE_ADMIN.SEGMENT_CORRUPT_CHECK('OWNER','SEG_NAME','TABLE');(仅用于触发刷新,非真校验)。











