新建普通表默认占64KB(8个8KB数据块),因DB_BLOCK_SIZE=8192且首次分配extent为64KB;分区表每个分区默认占8MB,源于11.2.0.2起_partition_large_extents默认为TRUE,强制分区段初始extent为1MB并配合MINEXTENTS=8。

新建普通表为什么默认占64KB(8个数据块)
因为 Oracle 在 11gR2 及之后版本中,默认启用 deferred_segment_creation(延迟段创建),但这个参数只对空表生效;而一旦执行了 INSERT 或显式分配空间(如建表时指定 INITIAL),Oracle 就会立即分配第一个 extent —— 普通表的默认 extent 大小是 64KB,即 8 个 8KB 数据块(假设 DB_BLOCK_SIZE=8192)。
常见误解是“建表语句一执行就占空间”,其实:如果建表后没插入任何数据、也没分析或触发段分配,dba_segments 里根本查不到该表的记录。真正触发空间分配的是第一次写入,或手动执行 ALTER TABLE ... ALLOCATE EXTENT。
-
DB_BLOCK_SIZE是关键前提:若库为 4KB 块,则 64KB = 16 个块;16KB 块则 = 4 个块 - 这个 64KB 是 最小 extent 大小,不是“固定值”:在
ASSM(自动段空间管理)表空间中,初始 extent 由表空间的INITIAL参数决定,通常设为 64KB - 如果是
SYSTEM表空间或老式DMSSM,可能按MINEXTENTS×INITIAL计算,但默认仍倾向 64KB 对齐
分区表每个分区为什么默认占 8MB?
这不是“表”的行为,而是分区段的独立分配策略。从 11.2.0.2 开始,Oracle 引入 _partition_large_extents 隐含参数,默认为 TRUE,强制分区表(包括 TABLE PARTITION、INDEX PARTITION)的首个 extent 设为 1MB(早期文档误传为 8MB,实际是 1MB × 8 = 8MB 的常见组合结果,源于默认 INITIAL 为 1MB 且 MINEXTENTS=8)。
验证方式很简单:
SELECT segment_name, partition_name, bytes/1024/1024 mb FROM dba_segments WHERE segment_name = 'YOUR_PART_TBL' AND segment_type = 'TABLE PARTITION';
你会发现哪怕只插一行,每个分区都显示约 8MB。这不是 bug,是设计选择:减少 extent 碎片、提升大表并发写入性能。
- 关掉它要改隐含参数:
ALTER SYSTEM SET "_partition_large_extents" = FALSE;(不推荐生产环境随意改) - 更安全的做法是在建分区表时显式指定:
STORAGE(INITIAL 64K),但需确保表空间支持小 extent(如使用UNIFORM SIZE 64K) - 注意:该参数不影响普通非分区表,只作用于
PARTITION类型段
怎么确认某张表到底占了多少真实块?
别只看 dba_tables.blocks,它只反映 HWM 下已格式化的块数,且不含索引、LOB、分区段。真正空间占用必须查 dba_segments 并按段类型聚合:
- 主表段:
SEGMENT_TYPE = 'TABLE'(非分区表)或'TABLE PARTITION'(分区表的每个分区) - 索引段:
SEGMENT_TYPE IN ('INDEX', 'LOBINDEX'),常比表本身还大 - LOB 段:
SEGMENT_TYPE = 'LOBSEGMENT',CLOB/BLOB 实际存储地,chunk 开销可能翻倍 - 执行
ANALYZE TABLE ... COMPUTE STATISTICS后,dba_tables.num_rows才准,但blocks仍是逻辑块数,不含未格式化块
一个典型陷阱:用 SELECT SUM(bytes) FROM dba_segments WHERE segment_name = 'T' 得到 50MB,但 SELECT COUNT(*) FROM T 只有 100 行 —— 这说明要么有大量已删除但 HWM 未降,要么存在隐藏的 LOB 或索引段没被计入查询条件。
删完数据后空间不释放?重点盯 HWM 和段移动
DELETE 不降低高水位线(HWM),TRUNCATE 会重置 HWM 但不能用于外键引用表或有物化视图依赖的场景。真正释放空间并压缩物理占用,得靠:
-
ALTER TABLE t ENABLE ROW MOVEMENT;(必须先开,否则SHRINK报ORA-10631) -
ALTER TABLE t SHRINK SPACE COMPACT;(先整理 HWM 下的空块,不移动段) -
ALTER TABLE t SHRINK SPACE CASCADE;(连带收缩索引,但要求所有索引也支持 shrink) - 最后才考虑
ALTER DATABASE DATAFILE ... RESIZE,但要注意ORA-03297:文件末尾仍有已分配块,必须先MOVE或SHRINK把段往文件头部挪
最易被忽略的一点:SHRINK 后索引可能失效(STATUS = UNUSABLE),LOB 索引可能损坏,执行计划也可能因统计信息过期而劣化——这些副作用往往比空间本身更影响业务。











