介绍Oracle DB Server 如何自动管理空间
• 使用压缩节省空间
• 主动监视和管理表空间的空间使用量
• 介绍Oracle DB 中的段的创建
• 控制延迟创建段
• 使用“段指导”
• 使用段收缩功能从表和索引中回收浪费的空间
• 管理可恢复的空间分配
空间管理:概览
空间由Oracle DB Server 自动管理。Oracle DB Server 可以生成有关潜在问题的预警,并推荐可能的解决方案。
这些功能包括:
• Oracle Managed Files (OMF)
• 用位图进行的空闲空间管理(“本地管理”)和数据文件自动扩展
• 主动的空间管理(默认阈值和服务器生成的预警)
• 空间回收(收缩段、联机重新定义表)
• 容量计划(增长报表)
空间管理:概览
通过使用Oracle ManagedFiles (OMF),你可以根据数据库对象(而不是文件名)来指定操作。Oracle DB Server 可以用位图来管理表空间内的空闲空间。这称为“本地管理的”表空间。此外,位于本地管理的表空间中的段内的空闲空间可以使用位图进行管理。这称为“自动段空间管理”。位图化的实施可以避免很多与空间相关的表优化工作,同时能在高峰负载期间提供更高的性能。另外,Oracle DB Server 还可以自动扩展数据文件,因此文件可以根据其中的数据量自动增长。
创建数据库时,默认情况下将启用预先空间监视。(这不会对性能产生任何影响。)
Oracle DB Server 在正常空间分配和取消分配操作期间监视空间使用情况,如果空闲空间的可用性低于预定义的阈值(可以覆盖此阈值),将发出预警。指导和向导可帮助你回收空间。
计划容量时,Oracle DB Server 根据表结构和行数进行空间估计,并根据自动工作量资料档案库(AWR) 中存储的历史空间使用情况来提供增长趋势报表。
块空间管理
块空间管理
空间管理包括块级别的空闲空间管理。使用“自动段空间管理”时,每个块分为四部分,分别称为FS1(空闲空间介于0 到25% 之间)、FS2(25% 到50% 空闲)、FS3(50% 到75% 空闲)和FS4(75% 到100% 空闲)。
块的状态将根据其中空闲空间的级别自动更新。这样,你就可以根据所插入行的长度来判断特定块能否满足插入操作的要求。请注意,“满”状态表示不能再向块中插入。
在示例中,左侧的块是一个FS3 块,因为其空闲空间介于50% 和75% 之间。执行了一些插入和更新语句后,将达到PCTFREE(虚线处),并且不能再向该块中插入新行。
现在该块被视为“满”或FS1 块。块的空闲空间级别一旦降至低于下一部分,就会考虑将该块再次用于插入。在上面这种情况中,空闲空间一旦超过25%,状态即变为FS2。
注:大对象(LOB) 数据类型(BLOB、CLOB、NCLOB和BFILE)不使用PCTFREE存储参数。未压缩块和OLTP 压缩块的默认PCTFREE值为10;基本压缩块的默认PCTFREE值为0。
行链接和行迁移
示例:
• 更新时:行的长度增加,超过了块中的可用空闲空间。
• 需要将数据存储在新块中。
• 将保留行的原始物理标识符(ROWID)。
• Oracle DB Server 需要读取两个块来检索数据。
• “段指导”查找包含迁移行的段。
• 可以对块中的碎片空闲空间进行自动合并。

行链接和行迁移
在以下两种情况下,表中某行的数据可能太大,无法包含在单个数据块中。
第一种情况:
在第一次插入行时,就发现行太大,无法包含在一个数据块中。在这种情况下,OracleDB Server 将在为该段保留的一系列数据块(一个或多个)中存储该行的数据。较大的行通常要进行行链接,例如包含数据类型为LONG或LONG RAW的列的行。在这些情况下,行链接是无法避免的。
但在第二种情况中,
最初可以包含在一个数据块中的行在更新后,整个行的长度增加了,而块的空闲空间已经完全填满。在这种情况下,Oracle DB Server 假定整个行可以包含在新数据块中,从而将整个行的数据迁移到新数据块中。数据库将保留迁移行的原始行片段,
以便指向包含迁移行的新块。迁移行的ROWID不变。
当行链接或迁移后,与此行关联的输入/输出(I/O) 性能会降低,因为Oracle DB Server 必须扫描多个数据块来检索该行的信息。
“段指导”查找包含由UPDATE操作产生的迁移行的段。
Oracle DB 在以下情况下会以自动透明方式合并数据块的空闲空间:
• INSERT或UPDATE语句尝试使用包含足够空闲空间的块来容纳新的行片段
• 空闲空间已成为碎片,以致于行片段无法插入到块的相邻部分
合并之后,空闲空间量与操作前的空间量相同,但空间现在是连续的。
当行链接或迁移后,与此行关联的I/O 性能会降低,因为Oracle DB Server 必须扫描多个数据块来检索该行的信息。
段内的空闲空间管理

段内的空闲空间管理
• 由段中的位图跟踪
好处:
• 空间使用更加灵活
• 运行时调整
•BMB 的多进程搜索
空闲空间管理
可以自动管理数据库段内的空闲空间。段内的空闲空间或已用空间由位图跟踪。要利用此功能,请在创建本地管理的表空间时,指定“自动段空间管理”。然后,指定的设置将应用于随后在此表空间中创建的所有段。
自动空间管理段具有一组位图块(BMB),用于描述该段中数据块的空间使用情况。BMB 以树形层次结构组织。层次的根层存储在段头部中,其中包含对所有中间层BMB 的引用。
此层次的各个叶节点代表属于该段的一组连续数据块的空间信息。此层次的最大层数为三。
使用自动空间管理的好处包括:
• 改善空间使用情况,尤其是各行大小差异很大的对象的空间使用情况
• 对并行访问发生的变化进行更好的运行时调整
• 在性能方面或空间使用方面改善多实例行为
因此,DBA 可以少做一些工作。
段的类型
段是为某个逻辑结构分配的一组区。段包括以下不同类型:
• 表和簇段
• 索引段
• 还原段
• 临时段
段由Oracle DB Server 动态分配。
段的类型
表和簇段:每个非聚簇表都有一个数据段。所有表数据都存储在表段的区中。对于分区表,每个分区都有一个数据段。每个集群也都有一个数据段。集群中每个表的数据都存储在集群的数据段中。
索引段:每个索引都有一个索引段,存储其所有数据。对于分区索引,每个分区都有一个索引段。
还原段:Oracle DB 会维护用于回退对数据库所做更改的信息。此信息包括事务处理操作的记录;这些操作统称为还原。还原信息存储在还原表空间的还原段中。
临时段:临时段是在SQL 语句需要临时数据库区域来完成执行时由Oracle DB Server 创建的。语句完成执行后,临时段中的区将返回到系统,以备将来使用。
如果段的现有区变满,Oracle DB Server 将动态分配空间。因为区是根据需要分配的,所以段中的区在磁盘上可能连续,也可能不连续。
分配区
• 搜索数据文件的位图,以便获取所需数目的相邻空闲块
• 可用以下存储子句调整区的大小:
– UNIFORM
– AUTOALLOCATE
• 查看区映射
• 获得取消分配建议

对于本地管理的表空间,Oracle DB Server 将查找要分配给新区的空闲空间,具体方法是:
先在表空间中确定候选数据文件,然后搜索数据文件的位图,以便获取所需数目的相邻空闲块。如果该数据文件没有足够的相邻空闲空间,则Oracle DB Server 将在另一数据文件中查找。
以下两个子句会影响区的大小调整:
• 使用UNIFORM子句,数据库可以按你指定的统一大小(或默认大小)为表空间中创建的所有对象创建所有区。
• 使用AUTOALLOCATE子句,数据库可以为表空间确定区大小调整策略。
要在Oracle EnterpriseManager 中查看区映射,请选择“Server > Tablespaces >View Tablespace > Show Tablespace Contents(服务器> 表空间> 查看表空间> 显示表空间内容)”。
Oracle DB Server 提供了“Segment Advisor(段指导)”,使用该指导可以根据对象中空间碎片的级别来帮助确定对象是否有空间可回收。
分配空间
新的空间分配方法:
• DEFERRED_SEGMENT_CREATION = TRUE(默认值)
1. Table creation > Datadictionaryoperation(创建表> 数据字典操作)
2. DML > Segment creation(DML > 创建段)

Oracle Database 11gR2 包含了一种新的空间分配方法。创建非分区堆表时,表段创建将延迟,直至插入第一行。该功能是默认启用的,即DEFERRED_SEGMENT_CREATION初始化参数设置为TRUE。
此新增的空间分配方法的优点包括:
• 对于安装时就会创建成百或上千个表(其中大多数可能永远不会填入内容)的应用程序而言,可以节省大量的磁盘空间。
• 缩短了应用程序安装时间。
在向表中插入第一行后,系统将为基表、其LOB 列及其索引创建段。在创建段期间,表上的游标将失效。这些操作会对性能产生较小的额外影响。
注:使用该新增的分配方法时,务必制定合适的容量计划以便有足够的磁盘空间用于处理填充表时的段创建操作,这一点非常重要。
创建没有段的表
SQL> SHOW PARAMETERSdeferred_segment_creation
NAME TYPE VALUE
----------------------------------------------- ------
deferred_segment_creation boolean TRUE
SQL> CREATE TABLE seg_test(c number, d varchar2(500));
Table created.
SQL> SELECT segment_name FROMuser_segments;
no rows selected
插入行并创建段:
SQL> INSERT INTO seg_test VALUES(1,'aaaaaaa');
1 row created.
SQL> SELECT segment_name FROMuser_segments;
SEGMENT_NAME
-------------------------------------------------------
SEG_TEST
创建没有段的表
本示例显示了如何检查DEFERRED_SEGMENT_CREATION参数。然后创建一个没有段的表,可通过查询USER_SEGMENTS数据字典视图进行验证。插入一行后,再次查询该视图以查看现在是否存在段。
还可以查询USER_TABLES、USER_INDEXES或USER_LOBS视图的SEGMENT_CREATED列。
对于非分区表、索引和LOB,如果创建了段,该列将显示YES。
数据字典中增加的另一个对象是SYS.SEG$表,该表用于存储在创建表或索引期间指定的存储参数。
控制延迟创建段
在以下项中使用DEFERRED_SEGMENT_CREATION参数:
• 初始化文件
• ALTER SESSION命令
• ALTER SYSTEM命令
使用SEGMENT CREATION子句:
• IMMEDIATE
• DEFERRED(Oracle Database11gR2 中的默认值)
CREATE TABLE SEG_TAB3(C1 number, C2number)
SEGMENT CREATION IMMEDIATE TABLESPACESEG_TBS;
CREATE TABLE SEG_TAB4(C1 number, C2number)
SEGMENT CREATION DEFERRED;
注:索引继承表的特征。
控制延迟创建段
可通过以下两种方式控制段的创建:
• 将DEFERRED_SEGMENT_CREATION初始化参数设置为TRUE或FALSE。可在初始化文件中设置该参数。还可以通过ALTER SESSION或ALTER SYSTEM命令进行控制。
示例:
ALTER SESSION SETDEFERRED_SEGMENT_CREATION = TRUE;
ALTER SYSTEM SET DEFERRED_SEGMENT_CREATION= FALSE;
• 使用CREATE TABLE命令的SEGMENT CREATION子句:
- SEGMENT CREATION DEFERRED:如果指定,则系统将延迟创建段直至表中插入第一行。这是Oracle Database 11gR2 的默认行为。
- SEGMENT CREATION IMMEDIATE:如果指定,则在表创建期间对段进行实体化。这是早于Oracle Database 11gR2 的Oracle DB 中的默认行为。
该子句优先于DEFERRED_SEGMENT_CREATION参数。
可以使用ALTER TABLE … MOVE命令为已创建的表强制创建段。
不过,对于从属对象(如索引),无法直接控制延迟创建段。它们继承其父对象(在本例中为表)的这一特征。
限制和例外
按需创建段:
• 仅适用于非分区表和索引
• 不适用于IOT、聚簇表或其它特殊表
• 不适用于字典管理的表空间中的表
注:如果计划将没有段的表从本地管理的表空间迁移到字典管理的表空间,则必须将其删除并重新进行创建。
限制和例外
• 在Oracle Database11gR2 中,延迟创建段被限制于非分区表和非分区索引。不支持IOT 和其它特殊表。
• 对于聚簇表和在字典管理的表空间中创建的表,不支持按需创建段。如果尝试这样做,系统将创建段。
• 如果在本地管理的表空间中创建了一个采用延迟创建段的表,则该表没有段。如果稍后将该表空间迁移到字典管理的表空间,则任何创建段的尝试都将产生错误。此时,必须将该表删除并重新进行创建。
• 对于聚簇表、全局临时表、特定于会话的临时表、内部表、类型化表、AQ 表、SYS拥有的表、外部表、位图联接索引以及域索引,不支持按需创建段。归SYSTEM、PUBLIC、OUTLN以及XDB所有的表也不在支持范围内。
其它自动功能
没有用户干预:
• 不能用的索引和索引分区没有段
• 创建没有段的索引:
CREATE INDEX test_i1 ON seg_test(c)UNUSABLE;
• 删除索引的任何已分配空间:
ALTER INDEX test_i UNUSABLE;
• 为索引创建段:
ALTER INDEX test_i REBUILD;
SELECT segment_name, partition_name,
segment_type
FROM user_segments
WHERE segment_name like '%DEMO';
其它自动功能
Oracle Database 11g发行版2 中还实施了其它增强功能(与延迟创建段无关)以节省空间:创建的所有UNUSABLE索引和索引分区都没有段。该功能对你是完全透明的。该功能默认为启用,即COMPATIBILITY初始刷参数设置为11.2.0.0。
示例:如果你有一个DEMO表,它有三个分区和一个本地索引,则在执行查询时会看到三个表段和三个索引段。
如果将一个表分区移至新的表空间,然后执行同样的查询,你将看到三个表段和两个索引段,这是因为不可用的一个已经自动删除。
表压缩:概览
通过压缩所有数据减少存储成本:
• 基本压缩适用于直接路径插入操作:10x
• OLTP 压缩适用于所有DML 操作:2–4x

典型应用压缩比率
{ COMPRESS[ BASIC | FOR { OLTP} ] |NOCOMPRESS }
表压缩:概览
Oracle DB 支持以下三种表压缩方法:
• 基本表压缩
•OLTP 表压缩
• Hybrid Columnar 压缩(通过Exadata)
Oracle Corporation 建议压缩所有数据以减少存储成本。Oracle DB 可使用表压缩来消除数据块中的重复值。对于具有高度冗余数据的表,压缩可节省磁盘空间并减少数据库缓冲区高速缓存中的内存使用。表压缩对数据库应用程序是透明的。
• table_compression 子句仅对按堆组织的表有效。COMPRESS关键字用于启用表压缩。
NOCOMPRESS关键字用于禁用表压缩。NOCOMPRESS为默认值。
• 通过基本压缩,Oracle DB 在使用诸如直接加载或CREATE TABLE AS SELECT等操作执行批量加载时压缩数据。
• 通过COMPRESS FOR OLTP,Oracle DB 在对表执行所有DML 操作期间压缩数据。
适用于直接路径插入操作的压缩
• 是使用CREATE TABLE…COMPRESS BASIC…;启用的
• 建议为批量加载数据仓库使用该压缩方法
• 替换已废弃的COMPRESS FORDIRECT_LOAD OPERATIONS
• 最大化块中的连续空闲空间

适用于直接路径插入操作的压缩
使用COMPRESS或COMPRESS BASIC可启用基本的表压缩。
• Oracle DB 在执行下列直接路径插入操作期间尝试压缩数据(如果这样做有利):
- 直接路径SQL*Loader
- CREATE TABLE AS SELECT语句
- 并行INSERT语句
- 带有APPEND提示的INSERT语句
• 原始导入实用程序(imp) 不支持直接路径INSERT,因此无法以压缩的格式导入数据。
• 在早期版本中,这种类型的压缩称为DSS 表压缩,是使用COMPRESS FOR DIRECT_LOAD OPERATIONS启用的。该语法已废弃。
• 压缩消除了块中因删除操作而形成的空隙,使块中连续可用空间达到最大化。
该幻灯片显示了压缩表中的数据块的演变过程,应按从左到右的顺序阅读。开始的时候,该数据块是空的,可以插入数据。开始在该块中插入数据时,数据以未压缩的格式存储(就像在未压缩的表中一样)。不过,只要该块达到其PCTFREE设置规定的填满标准,数据就会自动进行压缩,以减少其原来占据的空间。
这样一来,可以在同一块中插入新的未压缩数据,直到再一次达到PCTFREE设置规定的填满标准。此时,会再一次触发压缩以减少块中的已使用空间量。
注:采用COMPRESS或COMPRESS BASIC的表使用PCTFREE值0以最大化压缩,除非显式设置PCTFREE子句的值。
采用COMPRESS FOR OLTP或NOCOMPRESS的表使用PCTFREE的默认值10以最大化压缩,同时仍允许以后对数据进行一些DML 更改,除非显式覆盖该默认值。
适用于DML 操作的OLTP 压缩
• 是使用CREATE TABLE …COMPRESS FOR OLTP…;启用的
• 建议为活动的OLTP 环境使用该压缩方法
• 替换已废弃的COMPRESS FOR ALLOPERATIONS
适用于DML 操作的OLTP 压缩
使用COMPRESS FOR OLTP可启用OLTP 表压缩。
• Oracle DB 在对表执行所有DML 操作期间压缩数据。建议为活动的OLTP 环境使用这种形式的压缩。
• 在早期版本中,OLTP 表压缩是使用COMPRESS FOR ALL OPERATIONS启用的。该语法已废弃。
使用OLTP 压缩,一个数据块中行和列中的重复值只在块的开头存储一次(存储在符号表中)。重复值被替换为对符号表的简短引用(如图中所示)。因此,重新创建未压缩的数据所需的信息存储在块中。
为了说明OLTP 压缩的原理,示例中的图表显示了两个矩形。第一个灰色矩形包含四个标记为“G”的绿色小正方形和六个标记为“Y”的黄色正方形。它们表示未压缩的块。
在第二个灰色矩形的开头,仅有一个标记为“G”的绿色正方形和一个标记为“Y”的黄色正方形,表示符号表。第二个灰色图表在与绿色和黄色正方形相同的位置还显示了10 个白色的正方形。它们是白色的,因为它们现在仅是引用,重复值不占用空间。

扫描二维码关注我的微学堂
搜索刘老师微信号:Rman-2014,备注“Oracle学习与咨询”,即可添加好友;或者扫描下面二维码,关注我的“微学堂”公众号,了解最新OCP认证动态、题库及答案解析、培训机构及讲师介绍、课堂授课内容等。每天还有一篇技术文章发布哦!





