提示:公众号代码会自动换行,建议横屏阅读或左右滑动代码观看

为了保持其最强大和最灵活数据库的地位,Oracle在最近发布的几个版本里一直都在创建新的机制来对表格和索引的存储进行简化和分块。从Oracle8i开始,Oracle开始在Tablespace内部将对象管理进行自动化。第一个增强的地方原来叫做本地管理表空间Locally Managed Tablespaces(或者简写作LMT)。在LMT里,Oracle将Tablespace里的信息从数据字典的表格空间里移出去,而直接将其保存到Tablespace自身里。这在Oracle9i里已经成为了一个事实的标准,因为它减轻了数据字典的负担。
在Oracle 9i以前,表的剩余空间的管理与分配都是由链接列表 freelist 来完成的,因为freelist 存在串行的问题,因此容易引起段头的争用与空间的浪费(其实这一点并不明显),最主要的还是因为需要DBA花费大量的精力去管理这些争用并监控表的空间利用。
表格空间的第二个主要增强的是自动分段空间管理AutomaticSegment Space Management(ASSM),它首次出现在Oracle9i里。有了ASSM,链接列表freelist被位图bitmap所取代,它是一个二进制的数组,能够迅速有效地管理存储扩展和剩余区块(free block),因此能够改善分段存储本质。

管理空间的两种方法,让我们从比较这两种空间管理开始:
本地管理Tablespace(LMT)——LMT是通过把EXTENTMANAGEMENT LOCAL子句添加到Tablespace的定义句法而实现的。和原来由字典管理Dictionary Managed Tablespaces(DMT)不同,LMT会将扩展管理自动化,并保持OracleDBA不会被用来指定管理扩展大小的NEXT存储参数。这个原则唯一的例外是在NEXT和MINEXTENTS一起用在表格创建的时候。
自动区段空间管理(ASSM)——ASSM的Tablespace是通过将SEGMENT SPACE MANAGEMENT AUTO子句添加到Tablespace的定义语法里而实现的。通过使用位图bitmap取代传统单向的链接列表freelist,ASSM的Tablespace会将freelist的管理自动化,并取消为独立的表格和索引指定PCTUSED、FREELISTS和FREELIST GROUPS存储参数的能力。

Oracle值得赞扬的地方是,这两个空间管理的方法都是可选的特性,而且Oracle的老手可能仍会使用更加详细的方法,只要他们愿意的话。要注意,位图区段管理在Oracle 9i里是可选的,而且只能在Tablespace这一层实现,这一点是十分重要的。原有的系统还能够继续使用传统方法来管理freelist。
在讨论位图freelist和传统的空间管理之前,让我们看看位图freelist是如何实现的。从使用区段空间管理自动参数创建Tablespace开始:
CREATE TABLESPACE "SK_TD_DAT"
DATAFILE '+DATA/szswsky/datafile/sky_dat.dbf'
SIZE 2097152000
AUTOEXTEND ON NEXT 8192 MAXSIZE 32767M
LOGGING ONLINE PERMANENT BLOCKSIZE 8192
EXTENT MANAGEMENT LOCAL AUTOALLOCATE DEFAULT --turn on LMT
NOCOMPRESS SEGMENT SPACE MANAGEMENT AUTO --turn on ASSM
一旦定义好了Tablespace,那么表和索引就能够使用各种方法很容易地被移动到新的Tablespace 里,带有ASSM的本地管理Tablespace会略掉任何为PCTUSED、NEXT 和FREELISTS 所指定的值。
CREATE TABLE NEW_Test TABLESPACE ASSM_LMT_Test
AS
SELECT * FROM CUSTOMER;
ALTER INDEX Test_NAME_IDX REBUILD TABLESPACE ASSM_LMT_Test;
当表格或者索引被分配到这个Tablespace以后,用于独立对象的PCTUSED的值会被忽略,而Oracle 9i会使用位图数组来自动地管理Tablespace里表格和索引的freelist。对于在LMT的Tablespace内部创建的表格和索引而言,这个NEXT扩展子句是过时的,因为由本地管理的 Tablespace 会管理它们。但是,INITIAL参数仍然是需要的,因为Oracle不可能提前知道初始表格加载的大小。对于ASSM而言,INITIAL最小的值是三个块。
新的管理机制用位图来跟踪或管理每个分配到对象的块,每个块有多少剩余空间根据位图的状态来确定,如>75%,50%-75%,25%-50%和<25%,也就是说位图其实采用了四个状态位来代替以前的pctused,什么时候该利用该数据块则由设定的pctfree 来确定。
使用ASSM的一个巨大优势是,位图freelist肯定能够减轻缓冲区忙等待(buffer busy wait)的负担,这个问题在Oracle 9i以前的版本里曾是一个严重的问题。在没有多个freelist 的时候,每个Oracle表格和索引在表格的头部都曾有一个数据块,用来管理对象所使用的剩余区块,并为任何SQL插入声明所创建的新数据行提供数据块。当数据缓冲内的数据块由于被另一个DML事务处理锁定而无法使用的时候,缓冲区忙等待就会发生。当你需要将多个任务插入到同一个表格里的时候,这些任务就被强制等待,而同Oracle会在同时分派剩余的区块,一次一个。
有了ASSM之后,Oracle显著地提高了DML并发操作的性能,因为(同一个)位图的不同部分可以被同时使用,这样就消除了寻找剩余空间的串行化。根据Oracle的测试结果,使用位图freelist会消除所有分段头部(对资源)的争夺,还能获得超快的并发插入操作。
尽管ASSM显示出了令人激动的特性并能够简化Oracle DBA的工作,但是Oracle 9i的位图分段管理还是有一些局限性的:
1.一旦DBA被分配之后,它就无法控制Tablespace 内部的独立表格和索引的存储行为。
2.大型对象不能够使用ASSM,而且必须为包含有LOB数据类型的表格创建分离的Tablespace。
3.你不能够使用ASSM创建临时的Tablespace。这是由排序时临时分段的短暂特性所决定的。
4.只有本地管理的Tablespace 才能够使用位图分段管理。
5·使用超高容量的DML(例如INSERT、UPDATE和DELETE等)的时候可能会出现性能上的问题。

PCTFREE的问题
PCTFREE参数是用来指定数据块剩余空间大小的,这一空间为将来数据行的扩展而保留。如果PCTFREE设置得不得当,SQL的更新声明就可能导致大量的数据行碎片和断链。
数据行在刚保存的时候还很小,而在后来进行了扩展,在这种情况下,PCTFREE的设置就显得尤其重要了。在这样的系统里,通常会把PCTFREE设置成等于95,这就告诉Oracle要为数据行今后的扩展保留95%的数据区段空间。
PCTUSED的问题
对PCTUSED不正确的设置(例如设得太小了)会导致SQL插入声明性能的急剧下降。如果数据区块剩余空间不是很多,那么在SQL插入操作的过程中就会产生过量的I/O,这是因为被重新使用的Oracle数据区块会被迅速地填满。从极端的角度来看,没有正确地设置PCTUSED会导致数据区块的剩余空间要比表格数据行的平均长度小。在这样的情况下,Oracle会五次尝试从freelist链取回区块。在五次尝试以后,Oracle会提升表格的水位,并为插入操作腾出五个新的数据块。
有了Oracle 9i的ASSM,PCTUSED就不再控制表格数据块的重新链接阙值了,但是你必须依靠Oracle的判断来确定区块在什么时候会有足够的剩余空间放置到freelist里。
尽管有了本地管理的Tablespace和ASSM之后Oracle 9i会忽略PCTUSED、FREELISTS和FREELIST GROUPS等参数,但是当它们用于表格定义的时候,Oracle还是不会给出错误信息。
相关测试
1.先创建一个本地管理的表空间,采用段自动管理方式 :
CREATE TABLESPACE TEST
DATAFILE 'D:\APP\ORACLE\DATAFILE\TEST.dbf'
SIZE 50M
EXTENT MANAGEMENT LOCAL --一定是本地管理
SEGMENT SPACE MANAGEMENT AUTO; --ASSM管理的标志
2.创建同样一个表
CREATE TABLE TEST_TAB
(T_NO NUMBER) TABLESPACE TEST
STORAGE (INITIAL 1000 K);
指定初试区间大小是1000K
SELECT T.TABLE_NAME,
T.INITIAL_EXTENT,
T.NEXT_EXTENT,
T.PCT_FREE,
T.PCT_USED
FROM USER_TABLES T
WHERE T.TABLE_NAME = 'TEST_TAB';

3.执行该过程,检查表的初始状态

从这里我们能看到一些该表的特性,其中最引人注意的就是表头了,占用了三个块的大小(128-125),另外一个注意的地方就是该表从第128个块开始,文件头占用了1016K的空间等于127块。
我们从dba_extent中也能看到这样的信息,是从第128块开始的。
SELECT T.SEGMENT_NAME, T.EXTENT_ID, T.BLOCK_ID
FROM DBA_EXTENTS T
WHERE T.SEGMENT_NAME = 'TEST_TAB';

从这里可以看到,第一个区间的开始块是128,直接开始分析第 128,129,130 块(段头)
扫描下方二维码关注公众号,了解相关更新

更多阅读:




