本文希望通过系统地介绍这方面的有关概念
让大家能更好地规划使用数据空间
正确使用Oracle提供的有关功能特性
提高应用的执行效率
数据库空间的有效使用和维护不仅是数据库管理的重要工作也是大多数开发人员所关心的内容因为它直接关系到数据库性能的发挥同时数据碎片是经常令人头疼的问题碎片不仅造成空间的浪费更重要的是会直接影响应 用程序的响应速度
Oracle提供了不少方法用于数据空间的使用监控和维护同时也在各版本中陆续对这方面的功能进行了增强目的在于简化这方面工作的复杂度提高应用的运行效率
一相关概念
数据库的空间在逻辑上分为多个表空间每个表空间则由系统中的一个或多个物理数据文件构成Oracle存储数据的基本单位是块其大小在建库时由DB_BLOCK_SIZE参数确定一个或多个连续的块构成一个区片(EXTENT)它作为数据对象存储的基本单位来使用在Oracle中每个基本数据对象使用的空间称为段(Segment)段存放在唯一的表空间上每个段实际上是一系列区片(更为准确地是数据块)的集合每个简单数据对象对应一个段对于分区对象如分区表索引则每个(子)分区对应一个段由各个(子)分区共同构成一个完整的数据对象因此可以把表空间看作桶里面放着许多段一个段只能放在一个桶中而不能跨越多个桶
二表空间的使用
◆表空间碎片的产生
由于同一个表空间中存放有多个数据段各个数据段可以有不同的区片尺寸不同段的区片可以交叉存放当这些段中的区片经过分配(如创建表)释放(如删除表)后就可能使表空间中原本连续的空闲数据块变成不连续而区片必须由连续的数据块构成这时当某一段需要分配新的区片时就有可能出现虽然表空间空闲数据块的总和大于所需区片的大小但却无法找到一串连续的块来供此区片分配使用这种情况就称为表空间的Extent Fragmentation我们经常会遇到这种情况明明从DBA_FREE_SPACE中计算表空间还有几百MB但其中的某一个表却无法再扩展几个MB的空间
◆消除表空间碎片
Oracle在段的区片分配上为用户提供了很大的灵活性然而如果未能正确使用创建表空间和数据对象的各个可选择参数则在最后将不可避免的要面对区片碎片的问题Oracle 的Bhaskar Himatsingka 和 Juan Loaiza为此提出了SAFE(Simple Algorithm for Fragmentation Elimination)配制规则通过遵循这套规则区片级碎片可以完全的避免而实际上Oraclei引入的新特性Local Managed Tablespace就是SAFE规则在Oracle Server的内置实现SAFE原则概括起来包括
对每个表空间上的段使用相同的区片尺寸段参数INITIAL=NEXTPCTINCREASE=可以通过使用Create Tablespace 的 MINIMUM EXTENT 子句来确保分配的区片是此参数的倍数
仅在表空间级指定INITIALNEXT参数在创建数据段时不要指定这些参数
区片的大小根据段大小来确定原则是均衡顺序扫描的效率和空间的利用率同时确保段的区片数目控制在之下根据此原则在进行相应测试之后确定以下区片选取规则
段大小(Oracle) 区片大小(Oracle) 段大小(Oracle) 区片大小(Oracle) &M K &M K MG M MG M &G M &G M
有此数据库中可以只使用三种区片大小的表空间在对象创建之前需对其大小进行评估并放到相应的表空间中
Oracle引入了本地管理表空间它在管理和性能上都优于传统的字典管理表空间它已融合了规则 要使用此特性在CREATE TABLESPACE语句中指定EXTENT MANAGEMENT LOCAL子句
段的区片数目上限应在之下DML操作在此区片数目范围内不会有明显的性能差异但某些DDL操作的速度则与区片的数目关系较大因此合理的区片数目应保持在之下对于持续不断扩展的段应监控区片数目在必要时移至其它表空间
对于特别大的数据段应控制在G-G(Oracle为G-G)之间它们应存放到单独的表空间上同时对于这些特大段应考虑使用分区拉提高性能
用户的临时表空间应使用TEMPORARY类型
当系统的事务规模比较均衡时可以对回滚段使用OPTIMAL参数否则应避免制定OPTIMAL参数而定期监控回滚段的大小并在必要时重建
临时段和回滚段绝对不要将用户数据存放到SYSTEM表空间它是专为永远不会Drop和Truncate的系统数据对象而设计的
创建表空间时指定数据文件的大小应=区片整数倍+数据块对于Local Managed Tablespace则为区片整数倍+K
当表空间使用统一的区片大小时不要对其进行空间整理重整的结果不仅耗费精力而且可能会使性能变差对于未使用统一的区片尺寸的表空间应通过Export/Import重整
i 提供了Alter Table …Move [Tablespace…]命令可用于快速重整表Alter Index …Rebuild…[Tablespace…] 命令可用于快速重建索引
◆有关使用单个区片的误导
在许多关于碎片整理的文档中建议在Export时使用Compress=Y选项将表中的所有数据调整到一个区片中期望在Import后获得良好性能由此让许多人产生一个观点认为当表中数据全部存放到一个区片中时可以获得良好性能实际上单区片段只在以下条件成立时才具有优越性
◆数据主要以(全段)扫描方式访问
段所对应的数据块在物理磁盘上连续存放Oracle可以发布较大的顺序磁盘读操作
通过对这两条进行分析可以发现一方面数据库中大部分表是通过索引来访问另一方面现在的数据库文件一般在物理上使用了RAID或RAID+技术数据以条带化方式分布到多个物理磁盘上逻辑上的单个区片和多区片在物理上并无本质上的区别另外从Oracle的角度来看管理几百个区片的段是非常轻松的并不会有性能的下降由此可见将整个段放到一个区片中并无明显好处而这种做法却会导致表空间碎片的产生
三表数据段的使用
◆表空间的组织
Heap表的空间由一系列区片链接而成每个数据块除块头外其余部分可用于存放数据在创建表时可以指定以下参数
PCTFREE块中保留用于UPDATE操作的空间百分比当数据占用的空间达到此上限时新的数据将不能再插入到此块中
PCTUSED指定块中数据使用空间的最低百分比当一个块在达到PCTFREE之后经历了一些DELETE操作在其空间使用下降到PCTUSED后便可以重新被用于INSERT数据这就是PCTFREE/PCTUSED参数的含义
调整PCTFREEPCTUSED参数的目标一方面是提高性能另一方面则主要是提高空间使用效率避免出现块中存在有许多未用的空间但却无法找到一个块可以被用于插入新数据行的情况发生
◆PCTFREE的使用
在Oracle中表的每一行数据由唯一的ROWID标记而Oracle支持的数据类型中有一些长度是可变的如VARCHAR当对这些数据进行UPDATE时如果块中的可用空间不能容纳UPDATE后的数据行时Oracle将会把此行移到其它数据块同时保留此数据行的ROWID不变并在原有块中建一指针指向行迁移后的位置在这种情况下读取一行数据将需要访问个数据块从而导致性能下降PCTFREE保留的空间就是为确保更改后的数据行可以仍存放于原有数据块中避免行迁移的情况发生
由此如果PCTFREE设置不足时可能产生行迁移而另一方面如果PCTFREE设置过高将会造成空间浪费因此正确设置PCTFREE需要对表中数据的使用进行分析对于数据长度不会变化或极少更新的情况可以采用较小的PCTFREE对于其它大多数情况应采用稍大的PCTFREE(PCTFREE的缺省值是如果不好估计需预留的空间可以使用-的范围)不要为节约块中的空间而使用较小的PCTFREE值
◆PCTUSED的使用
当块的使用的空间下降到PCTUSED后此块被重新放回空闲链表(Freelist)中作为后续Insert的候选块同样设置PCTUSED需要视数据行的特性和InsertUpdateDelete的模式而定但必须遵守的原则是db_block_size * ( PCTFREE PCTUSED)必须比行的长度大
对于数据行长度变化较大的情况应使用最大行长度来计算PCTUSED并且应使用较低的PCTUSED值因为在执行Insert时如果数据块的可用空间不能装下一行数据当块的使用的空间是在PCTUSED之上Oracle将把此块从Freelist中移走当块的使用的空间是在PCTUSED之下Oracle将会扩展段空间因此PCTUSED如果设得过高将导致段的不断扩展
当数据行长度不大时使用缺省的PCTUSED()是比较合适的对于行长度较大的情况最长的行有可能会占用半个以上的块空间此时可设置PCTUSED为较小的PCTUSED仅在表中的数据以随机方式被删除而且仍有一些行长时间保留在块中时才会造成空间使用上的问题因为这些块可能需要较长的时间才能或永远不能重新被用于存放新数据在这种应用中如果空间利用率一直处于较低水平则需对PCTUSED进行分析和调整