LMT通过文件头位图管理空闲区,分配/释放extent仅修改位图,无需递归SQL或字典锁,从根本上避免表空间级碎片;COALESCE对其无效,所谓“小空闲片段”多源于应用频繁创建删除小对象。
为什么 LMT 本身就能大幅降低表空间级碎片
本地管理表空间(lmt)不依赖数据字典表(如 fet$、uet$)记录空闲 extent,而是用每个数据文件头部的位图(bitmap)直接标记块/区的使用状态。这意味着:分配或释放一个 extent 只需修改几个位,不触发递归 sql、不争抢数据 dictionary latch,也不产生额外锁。碎片问题在分配层面就被消解了——你不会看到“几十个 8kb 空闲 extent 散落在各处却凑不出一个 64kb 段”的情况。
关键点在于:COALESCE 命令对 LMT 完全无效,执行后无报错也无动作;LMT 下所谓“大量小空闲片段”,通常不是位图管理缺陷,而是应用频繁创建/删除小对象(比如临时表、会话级 GTT)导致的 autoallocate 分配模式下的自然现象。
LMT 的两种 extent 分配策略怎么选
创建 LMT 时必须指定 AUTOALLOCATE 或 UNIFORM SIZE,二者行为差异直接影响空间布局和长期碎片倾向:
-
AUTOALLOCATE:Oracle 自动从 64KB 起步,随段增长逐步升到 1MB、8MB、64MB。适合 OLTP 场景,小表不浪费,大表不卡顿;但若存在大量短生命周期的小对象(如日志表按天 truncate),可能积累较多小 extent,DBA_FREE_SPACE中BLOCKS行数偏高——这不是故障,只是位图如实反映现状 -
UNIFORM SIZE:所有 extent 强制等大(如UNIFORM SIZE 1M)。适合数仓或归档表空间,extent 大小一致,物理分布更规整;缺点是小对象也会占满整个 extent,空间利用率略低,且一旦设错(比如设成 128MB 却存千万行小表),反而造成内部浪费
检查当前表空间策略:SELECT tablespace_name, allocation_type, initial_extent FROM dba_tablespaces
真正需要干预的“碎片”往往不在表空间层
很多人看到 DBA_FREE_SPACE 里空闲 extent 数量多,就以为是“碎片”,急着想合并。但 LMT 下这些数字只表示“当前未被任何段占用的逻辑单元数量”,和性能无关。真正影响性能的,是段内(segment-level)问题:
- 表的高水位线(HWM)长期不降:删掉 90% 数据后 HWM 还卡在顶部,全表扫描仍要读大量空块 → 用
ALTER TABLE ... SHRINK SPACE COMPACT先整理再收缩 - 索引叶块稀疏:删除大量记录后
del_lf_rows / lf_rows > 0.2,且height > 4→ 重建索引比调表空间参数管用得多 - 分区表空分区泛滥:间隔分区(
INTERVAL)没预建预留分区,每次插入新时间范围都自动建一个空分区 → 改用显式预建 +SET INTERVAL控制
盲目在 LMT 上反复执行 COALESCE,只会徒增 SQL 解析开销,还可能干扰 SMON 对其他 DMT 表空间的自动合并调度。
确认是否真为 LMT 及后续操作前提
别跳过验证直接操作。先跑这条语句:
SELECT tablespace_name, extent_management, allocation_type FROM dba_tablespaces WHERE tablespace_name = 'YOUR_TS';
只有当 extent_management = 'LOCAL' 时,才属于 LMT;此时若 allocation_type 是 AUTOALLOCATE,说明它本就不该也不需 coalesce;若是 UNIFORM,更要警惕是否因初始 size 设得过大/过小引发段内空间浪费。
复杂点在于:LMT 解决的是“分配管理碎片”,但业务逻辑导致的对象生命周期混乱、HWM 滞留、索引分裂等问题,依然存在,且更难被监控工具直接标出。处理前务必分清问题层级——是表空间头位图的事,还是某个具体表段的事。


















