6.1 表空间
表空间分为两类:一类叫系统表空间(system tablespace),系统表空间是在创建数据库时创建的,包含了所有的数据字典信息;另一类叫做非系统表空间(non-system tablespace),这些表空间由DBA根据需要创建,可以包含用户自己的数据,也可以包含临时数据以及undo数据。
一般来说,我们会根据业务逻辑来为数据库划分表空间。比如,我们有一个业务系统数据库,可以在其中创建销售类表空间、采购类表空间、财务类表空间以及人力资源类表空间等。我们把销售类数据放入销售类表空间,而将采购数据放入采购类表空间等。
6.1.1 表空间的空间管理
所谓表空间的空间管理,是指对表空间里的segment的扩张和收缩进行管理。而我们知道,segment的扩张和收缩的最小单位就是extent,因此,表空间的空间管理也就是如何管理extent的分配和释放。其管理存在两种方式:数据字典管理(Dictionary Management Tablespace,简称DMT)和本地管理(Locally Management Tablespace,简称LMT)。
对于数据字典管理来说,采用两个数据字典表FET$和UET$来管理extent的扩张和收缩。FET$也就是Free ExtenT的缩写,用来记录表空间中的可用空间。而UET$也就是Used ExtenT的缩写,用来记录表空间中已经被分配掉的空间。我们来看FET$和UET$的结构。
SQL> desc fet$ Name Null? Type ---------------------------------------------------- TS# NOT NULL NUMBER FILE# NOT NULL NUMBER BLOCK# NOT NULL NUMBER LENGTH NOT NULL NUMBER SQL> desc uet$ Name Null? Type ----------------------------------------------------- SEGFILE# NOT NULL NUMBER SEGBLOCK# NOT NULL NUMBER EXT# NOT NULL NUMBER TS# NOT NULL NUMBER FILE# NOT NULL NUMBER BLOCK# NOT NULL NUMBER LENGTH NOT NULL NUMBER
在FET$中,记录了表空间号(TS#)、数据文件号(FILE#)、数据块号(BLOCK#)以及长度(LENGTH)。从LENGTH字段可以看出,该表里记录的是一块块连续的空间。假设我们新建一个含有50个数据块的表空间,同时假定其表空间名为TBS1,表空间号为20,数据文件号为28,则该表里就只有一条记录,因为这整块空间都是连续的。也就是:
TS# FILE# BLOCK# LENGTH 20 28 1 50
对于UET$来说,其中记录了extent的编号(EXT#)。也就是说,一个extent占一条记录。同时它还记录了该extent所在的表空间、数据文件、extent的第一个数据块的块号、以及extent包含多少个数据块(LENGTH字段)。当然,对于我们刚才新建的表空间来说,里面没有任何的segment,也就不会在UET$里存在对应的extent。
通过字典来管理extent的分配,也就是通过在这两个表之间转移数据行来实现的。现在,假设我们在TBS1中创建一个名为T1的表,一次扩张一个extent,一个extent由8个数据块组成,初始大小为一个extent。于是,我们要从TBS1里挖走一块空间,并更新FET$为:
TS# FILE# BLOCK# LENGTH 20 28 9 42
因为我们把块号从1到8的这8个数据块挖走作为表T1所占据的空间,所以剩下的连续空间从第9个块开始,共包含42个数据块。同时,由于我们已经使用了8个数据块生成了extent,则还要更新UET$(假设表T1的第一个extent的编号为100):
EXT# TS# FILE# BLOCK# LENGTH 100 20 28 1 8
接下来,我们又在TBS1里创建了另一个表T2,该表一次扩张一个extent,一个extent由12个数据块组成,初始大小为一个extent。于是,仍然从TBS1里挖一块空间,并更新FET$为:
TS# FILE# BLOCK# LENGTH 20 28 21 30
并将新产生的extent体现到UET$里去:
EXT# TS# FILE# BLOCK# LENGTH 100 20 28 1 8 101 20 28 9 12
依此类推,在字典管理的表空间中,extent的分配就像我们上面所描述的那样,不断从FET$里挖走空间,并将挖走的空间插入到UET$里。假设经过一段时间的数据插入操作,并引起extent不断被分配,导致目前的FET$如下所示:
TS# FILE# BLOCK# LENGTH 20 28 48 2
而UET$则为:
EXT# TS# FILE# BLOCK# LENGTH 100 20 28 1 8 101 20 28 9 12 ……
现在,用户删除了表T1的数据,导致表T1的第一个extent也就是100号extent被释放了。于是,Oracle将100号extent从UET$里删除:
EXT# TS# FILE# BLOCK# LENGTH 101 20 28 9 12 ……
同时,由于该空间被释放,从而又变成可用的连续空间,于是更新FET$:
TS# FILE# BLOCK# LENGTH 20 28 48 2 20 28 1 8
接下来,用户又删除了表T2的数据,导致表T2的第一个extent也就是101号extent也被释放了。于是,Oracle将101号extent从UET$里删除:
EXT# TS# FILE# BLOCK# LENGTH ……
同时,由于该空间被释放,从而又变成可用的连续空间,于是更新FET$:
TS# FILE# BLOCK# LENGTH 20 28 48 2 20 28 1 8 20 28 9 12
然后,用户又在TBS1里创建了一个新的表T10,该表一次扩张一个extent,一个extent由18个数据块组成,初始大小为一个extent。也就是说,为创建该表,至少需要一个由18个数据块组成的连续空间。
我们在FET$里可以看到目前共有三块连续的可用空间,分别是由2个block组成、8个block组成以及12个block组成。没有一个连续的空间满足要求(18个数据块组成)。但是我们仔细查看第二条和第三条记录,一块空间从1号数据块到8号数据块,下一块空间从9号数据块开始。这两条记录所标明的连续空间明显是紧挨在一起的,是可以提供所需要的空间的。为了避免这种情况发生,SMON进程会定期负责合并这种所谓的相邻可用空间。也就是将FET$表更新为:
TS# FILE# BLOCK# LENGTH 20 28 48 2 20 28 1 20
这样,如果我们需要18个数据块组成的连续空间的需求就能够得到满足了。
从上面描述的字典管理的extent机制中,我们可以总结出以下问题。
⊙ 当用户进程对表进行DML操作,从而需要空间时,Oracle会产生很多的递归SQL,通过这些递归SQL完成对FET$和UET$的更新。
⊙ 因为要在FET$与UET$这两个表之间插入和删除记录,因此需要产生很多的事务,事务都会引起锁定。如果多个进程同时要求扩张extent时,大家都会去试图更新FET$里的相同记录,于是引起锁定等待。因为一次只能由一个进程对一条记录进行DML,其他进程只有在该事务提交或回滚以后才能对相同的记录进行DML操作。
⊙ 因为产生事务,所以会产生undo和redo。
⊙ SMON进程要定期扫描FET$表,对其中相邻的可用空间进行合并。这会消耗一定的资源,当FET$中记录数很多的时候,资源消耗尤其严重。
正是为了解决字典管理的表空间所具有的这些问题,Oracle才会引入本地管理的表空间。在本地管理的表空间中,不再采用FET$和UET$这两个表来记录extent的分配和使用,而是在数据文件头部选出6个数据块(从第3个块一直到第8个块),在其中存放bitmap来管理extent的分配和释放。
数据文件头部的bitmap由多个bit位组成,该bitmap看起来像这样:
11110011010101000011110101011……
其中的每个1或0就表示一个bit位,而每个bit位则对应一个extent,或者多个bit位对应一个extent(因为有时一个extent过大,就会有多个bit位共同来对应一个extent)。1表示对应的extent已经被某个segment使用了,而0则表示对应的extent还不属于任何的segment,可以被用。假设对于上面显示的例子来说,一个bit位就对应一个extent,则在该数据文件中的前4个extent都已经被分配了;第5、6两个extent没有被使用;第7、8两个extent被分配了。依此类推。
当进程需要extent时,只要扫描文件头部的bitmap,找到那些值为0的bit位,并分配该bit位对应的可用空间,然后将该bit位从0设置为1。由于删除数据而释放extent时,则需要将释放的extent所对应的bit位的值从1改为0。
从这里,我们可以看到,它有效地克服了字典管理的表空间的弊端。由于在本地管理extent中,分配及释放extent时只需要修改文件头部即可,速度快且不存在事务,因此也就没有递归SQL、事务锁以及redo和undo的问题。同时,很明显的,两个连在一起的0所对应空间必然是连续的,因此也不存在合并相邻可用空间的问题。
因此,从Oracle 9i开始,我们就应该创建本地管理的表空间,而不是数据字典管理的表空间。
6.1.2 创建和管理表空间
Oracle 10g中创建和管理表空间非常容易,可以直接借助于图形界面Database Control完成。如图6-1所示。
图6-1 创建表空间
⊙ 点击上图的①部分中的“Tablespaces”链接。
⊙ 进入上图中的②部分,该界面显示数据库所有的表空间,单击Create按钮。
⊙ 进入上图中的③部分。在其中输入表空间的名称,比如为MYTBS。
Extent Management部分的单选框
● Locally Managed:表示MYTBS为本地管理的表空间。
● Dictionary Managed:表示MYTBS为字典管理的表空间。
Type
● Permanent
表示该表空间存放的是永久性对象。复选框“Set as default permanent tablespace”的含义为,如果选中则说明MYTBS为数据库的默认永久表空间。如果我们在创建用户时没有为该用户指定默认的表空间,则使用MYTBS作为该用户的默认表空间。在该用户下创建对象时,只要没有明确说明所属表空间,就把对象放在MYTBS下。如果没有指定数据库的默认永久表空间,同时在创建用户时也没有明确地指定其默认永久表空间是哪个,则会使用系统表空间作为该用户的默认永久表空间。数据库级别的默认永久表空间不能被删除,除非为数据库指定了另外一个表空间为新的默认永久表空间。如果使用dbca创建数据库,则会自动创建一个名为users的永久表空间,并将其作为数据库的默认永久表空间。使用下面查询确定当前默认永久表空间:
SQL> select property_value from database_properties 2 where property_name='DEFAULT_PERMANENT_TABLESPACE'; PROPERTY_VALUE ----------------------------------------- USERS
⊙ Temporary
表示MYTBS表空间为临时表空间。临时表空间主要用来存放用户的临时数据(临时数据就是在需要时被覆盖,关闭数据库以后被删除),其中不能存放永久性数据。临时表空间可以被所有用户所使用。
比如当用户对很多数据行进行排序时,从前面我们已经知道,排序会在PGA里完成。如果排序的数据太多,导致内存不足时,则Oracle会将要排序的数据分割成多份,只取一份放在PGA里进行排序,其他的部分都交换到临时表空间里去。当PGA里的部分排序完毕以后,将排好序的部分交换到临时表空间里,同时再从临时表空间里取一份没有排序的数据放到PGA里进行排序。依此类推,直到将所有的数据都排序完毕为止。
复选框“Set as default temporary tablespace”的含义为,如果选中则说明MYTBS为数据库的默认临时表空间。这样如果我们在创建用户时没有为该用户指定默认的临时表空间,则使用MYTBS作为该用户的默认临时表空间。该用户所发出的所有排序等操作都会使用MYTBS作为数据临时的存放地。如果没有为数据库指定一个默认临时表空间,同时在创建用户时也没有明确地指定其默认临时表空间是哪个,则会使用系统表空间作为该用户的临时表空间。数据库级别的默认临时表空间不能被删除,除非为数据库指定另外一个表空间为新的默认临时表空间。如果使用dbca创建数据库,则会自动创建一个名为temp的临时表空间,并将其作为数据库的默认临时表空间。使用下面查询命令确定当前默认临时表空间:
SQL> select property_value from database_properties 2 where property_name='DEFAULT_TEMP_TABLESPACE'; PROPERTY_VALUE ----------------------------------------- TEMP
● Undo:说明MYTBS为undo表空间,具体参见第7章。
Status
● Read Write:说明该表空间为可读可写。默认为该状态。
● Read Only
说明该表空间为只读状态,不能写入。系统表空间、默认临时表空间以及undo表空间都不能设置为只读。将一个表空间设置为只读以后,该表空间里的表所含的数据不能被修改,但是表是可以被删除的。因为删除一个表只是更新系统表空间里的数据字典,在数据字典中,将有关该表的定义信息删除而已,并不实际地删除该表所包含的数据本身。
⊙ Offline
说明该表空间为离线状态,既不能读也不能写。系统表空间、默认临时表空间以及undo表空间都不能设置为Offline。
⊙ 单击Add按钮,进入④部分,为表空间添加数据文件。
Datafiles部分则让我们指定该表空间所包含的数据文件的信息。我们看到下面有个复选框“Use bigfile tablespace”。该选项从Oracle 10g起引入,选中该复选框则说明表空间为大文件表空间。对于大文件表空间来说,只能包含一个数据文件,在这一个数据文件里最多可以包含40亿个数据块。随着数据块大小的不同(数据块大小为2KB、4KB、8KB、16KB或32KB),该数据文件最小可以达到8TB (数据块为2KB),最大可以达到128TB(数据块为32KB)。大文件表空间最大的好处就是减少了数据文件的数量,从而简化了数据文件的管理。如果没有把bigfile放在ASM里,而是放在文件系统里的话,则所在的文件系统必须支持大文件。
如果不选中该复选框,就是smallfile。创建表空间时,默认就是smallfile,这时可以为表空间创建多个数据文件。单击Add按钮,弹出图6-1中的④部分,在这里,可以添加数据文件。
我们为数据文件输入文件名称、文件所在路径及文件大小尺寸。
我们看到一个名为“Reuse Existing File”的复选框,如果选中该复选框,则表示输入的文件已经存在,并重用该文件。
在Storage部分,如果不选中名为“AUTOEXTEND”的复选框,则说明该数据文件在空间耗尽以后报错。反之,如果选中则会自动增长,而且我们还要在Increment字段中输入每次增长多少空间。同时,如果为自动增长,我们还需要指定该文件的最大尺寸,默认为unlimited,我们可以在value字段部分输入该文件的最大尺寸。
确定输入的信息以后,单击Continue按钮即可。如果表空间不是bigfile,则还可以继续添加其他的数据文件。
⊙ 我们单击图6-1中③部分中的“Storage”标签,进入⑤部分所示的界面,在这里,可以输入有关表空间的存储参数。
Extent Allocation:该选项说明,当我们选择了本地管理的表空间时,该表空间里所包含的segment的extent到底有多大,有以下两个选择。
● Automatic:由Oracle根据segment当前所含有的extent的个数来确定下一次扩展(也就是下一个extent)应该为多大。当前segment的extent个数越多,则下一个extent也会越大。
● Uniform:说明表空间里所有的segment的extent大小都相同。同时需要在Size字段输入表空间里的每个extent为多大。建议选择Uniform的类型,这样不会产生extent级别的碎片。
注 意 我们在规划表空间时,一般先按照业务逻辑进行划分。比如分成销售类(sales)、采购类(pur)、财务类(fin)以及人事类(hr)这四类;然后再按照表所含有的数据量的大小来划分,一般分为三类:大表、中表、小表。所有表空间都使用本地管理以及uniform size组合。大表所在表空间的extent最大(比如为8MB)、中表中等(比如为1MB)、小表最小(比如为64KB)。这样,我们就可以规划销售类表空间包含三个具体的表空间:sales_big_tbs、sales_middle_tbs、sales_small_tbs。依此类推,为剩下的三类业务表空间以同样方式指定,从而我们总共得到12个表空间。
Segment Space Management:该选项从Oracle 9i引入,用来说明在向表里插入数据时,在segment里的extent里,如何选择一个可用的数据块来放数据。
⊙ Manual
Oracle 9i之前,我们只能以手工设定参数方式来确定哪个数据块可以用来进行插入操作,该方式如图6-2所示。
图6-2 Freelist的结构图
该方式下,DBA为segment定义可用链表(freelist),freelist上挂的都是可以用来进行插入操作的数据块。该可用链表的起点记录在segment header里,也就是segment的第一个数据块里。当服务器进程进行插入而需要可用块时,先锁定segment header,然后在可用链表上搜索具有足够空间进行插入的可用数据块,找到该数据块以后,将数据插入,最后释放对segment header的锁定。选择具体数据块的过程则如图6-3所示。
图6-3 选择可用数据块的过程
在创建表或者索引等segment时,我们可以指定两个参数:pctfree和pctused。
pctfree表示数据块里剩余的可用空间占数据块总空间的百分比,该参数默认为10。pctused表示数据块里已经使用的空间占数据块总空间的百分比,该参数默认为40。当可用链表上的某个数据块不断被插入数据,从而导致该数据块里的剩余可用空间与数据块大小的百分比小于pctfree的值的时候,该数据块从可用链表上摘除,不能再用于插入操作。数据块从可用链表上摘下以后,剩余的可用空间将被更新操作所使用。因为对数据块里已经插入的数据的更新可能会引起对可用空间的需求,比如对数据行中的某个列更新成更长的值等。
当我们删除某个数据块上的数据,导致该数据块里已经使用的空间与数据块大小的百分比小于pctused的值的时候,则说明该数据块的可用空间足够多了,于是再次被挂到可用链表上。
当某个segment上的并发插入很严重的时候,由于搜索可用链表时只能由一个进程锁定segment header,因此其他要插入的进程就必须等待,从而出现segment header上的争用等待。
⊙ Automatic
自动段空间管理,简称ASSM(Automatic Segment Space Management),在Oracle 9i引入。表示使用类似索引的结构来管理segment中的数据块。为此,Oracle引入了所谓的BMB块(bitmap blocks),这些BMB块与数据块一起,分布在整个segment里。其结构如图6-4所示。
这些BMB块组织成类似索引树状的结构,一共三个层级:第一级BMB类似索引里的叶子节点,其中包含数据块的地址以及每个数据块的使用状态;第二级BMB则类似索引里的分支节点,其中包含第一级BMB块的地址;第三级BMB则类似索引里的根节点,其中包含第二级BMB块的地址。不过只有当segment里的数据量非常大的时候才会分裂出第三级BMB。
当服务器进程需要找可用数据块来插入数据时,则只要根据各个层级的BMB的关联关系,找到第一级BMB即可。第一级BMB中记录了若干个数据块的地址以及它们的使用状态。Oracle将该使用状态分为6个等级:Unformated(数据块还没有被格式化)、<25%(数据块的可用空间小于25%)、25%~50%(数据块的可用空间为25%到50%)、50%~75%(数据块的可用空间为50%到75%)、75%~100% (数据块的可用空间为75%到100%)、Full(数据块没有可用空间)。
图6-4 ASSM的结构图
因此,服务器进程根据插入的数据量的大小,来判断应该用哪个数据块。假设当前的插入需要使用1KB的空间,同时数据块为8KB大小,则需要12.5%(1KB/8KB)的空间。于是在叶子BMB块中找一个可用空间大于12.5%的数据块即可。当完成数据插入以后,把被插入的数据块剩余的可用空间状态信息更新BMB块中对应的的条目。ASSM必须在本地管理的表空间上使用。
引入了ASSM以后,使用多个BMB而不是可用链表,因此多个进程可以同时使用多个BMB进行并行的插入,从而有效地防止了对segment header的争用等待。Oracle建议设置为ASSM。在ASSM的表空间里创建segment的时候,只能指定pctfree,而pctused、freelist等存储参数被忽略。
Enable logging
● Yes:说明对该表空间里的表进行DML时都产生重做记录。
● No:说明对该表空间里的表进行DML时都不产生重做记录。这样做,可以加快DML的速度,但是不安全。
输入完毕所有的信息以后,我们可以单击Show SQL按钮,查看创建表空间的SQL命令。比如对于上面我们的例子来说,其创建命令为:
CREATE SMALLFILE TABLESPACE "MYTBS" DATAFILE '/u01/app/oracle/oradata/ora10g/mytbs01.dbf' SIZE 100M AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M SEGMENT SPACE MANAGEMENT AUTO
在Oracle 10g中,如果使用dbca创建数据库,并在创建数据库时选择了Sample Schema时,那么系统就会预先建立一些表空间。我们进入Database Control,单击Administration→Tablespace,进入表空间列表界面,如图6-5所示。
可以看到,system表空间为数据字典存放的表空间;sysaux表空间从Oracle 10g起引入,作为辅助系统表空间,其重要程度与system表空间一样,也是在创建数据库时创建,不能重命名、不能删除。在sysaux里存放了很多数据库的辅助功能,比如AWR等。我们可以在图6-5中选中sysaux表空间,然后单击View按钮,可以看到Occupants of SYSAUX部分,这部分就显示了sysaux里存放了哪些对象;temp表空间为数据库默认临时表空间;undotbs1为数据库的undo表空间;users为数据库默认永久表空间;example则为数据库测试用例涉及的表所属的表空间。
图6-5 表空间列表
在创建完毕表空间以后,还可以对表空间的设置进行修改。我们可以在图6-5中选中要修改的表空间,比如选中“Example”,然后单击Edit按钮即可修改,如图6-6所示。
图6-6 修改表空间
有些属性只能在创建表空间时指定,而不能在创建完以后修改,比如Extent Management等。如果使用Database Control,则只有可以修改的属性才能让我们编辑。在Oracle 10g里,我们可以直接修改表空间的名称,而不需要重建表空间。如果修改status,需要注意Offline的问题,有四种设置Offline的方式。
⊙ Normal:这种方式下,在离线之前,Oracle会发出文件级别的CKPT,从而将要离线的表空间所对应的位于buffer cache里的脏数据块全部写入对应的数据文件里,然后将表空间离线。通过这种方式离线的表空间数据没有损坏,下次online时不需要恢复。
⊙ Immediate:通常在表空间所对应的数据文件全部丢失或损坏的情况会采用这种模式。这时,Oracle不会发出文件级别的CKPT,所有脏数据都不写入。这种方式离线的表空间数据会被损坏,下次online时需要恢复。
⊙ Temporary:通常在表空间所对应的数据文件没有完全丢失或损坏的情况会采用这种模式。这时,Oracle会发出CKPT,能写入的脏数据就写入,不能写入的就不写入。这种方式离线的表空间数据会被损坏,下次online时需要恢复。
⊙ For Recover:这种模式已经被废弃了。
我们还可以对表空间里的数据文件进行修改,在图6-6中Datafiles部分中选中要修改的数据文件,然后单击Edit按钮,如图6-7所示。
图6-7 修改数据文件
在该界面上,我们可以offline数据文件、扩大或收缩数据文件、设置数据文件的自动扩展以及指定数据文件最大尺寸等属性。
如果我们要把数据文件从A目录下转移到B目录下,则使用Database Control无法完成,需要使用命令。转移表空间分两种情况:转移非system表空间的数据文件和转移system表空间的数据文件。如果要转移非system表空间,比如将example01.dbf从/u01/ora10g转移到/u02/ora10g,则依次执行如下的命令:
SQL> alter tablespace example offline; SQL> !cp ‘/u01/ora10g/example01.dbf’ ‘/u02/ora10g/example’ SQL> alter tablespace example rename datafile ‘/u01/ora10g/example01.dbf’ to ‘/u02/ora10g/example’; SQL> alter tablespace example online;
如果要转移system表空间,将system01.dbf从/u01/ora10g转移到/u02/ora10g,则依次执行如下的命令:
SQL> shutdown immediate; SQL> startup mount; SQL> !cp ‘/u01/ora10g/system01.dbf’ ‘/u02/ora10g/system01.dbf’ SQL> alter database rename datafile ‘/u01/ora10g/system01.dbf’ to ‘/u02/ora10g/system01. dbf’; SQL> alter database open;
在管理表空间时,我们还可以在图6-5所示的界面中,先选择要管理的表空间,然后选择Actions。如图6-8所示。这里可以看到有很多选项,包括添加数据文件、设置为只读等。我们选择这些选项以后,基本都可以单击Show SQL按钮查看具体执行的SQL命令。
对于不需要的表空间,我们可以进行删除,可以使用Database Control完成。在图6-5所示的界面中单击Delete按钮。也可以使用SQL命令完成:
drop tablespace <ts_name> including contents and datafiles ;
如果表空间中已经存在对象了,则必须添加including contents。添加and datafiles表示在删除表空间的同时,删除表空间所包含的数据文件。
图6-8 管理表空间
6.1.3 临时表空间和临时表空间组
我们前面说过,临时表空间主要是用来存放用户的临时数据的,比如排序数据等。可以使用Database Control来创建临时表空间,也可以使用SQL命令,比如最常用的命令为:
create temporary tablespace temp tempfile '/u01/app/oracle/oradata/ora10g/temp01.dbf' size 100M autoextend on;
在Oracle 10g中,我们还可以定义临时表空间组。临时表空间组是一组临时表空间,只能由临时表空间组成。临时表空间组与临时表空间的名字不能相同。临时表空间组不能显式地创建和删除。当把第一个临时表空间被分配给某个临时表空间组时,自动创建该临时表空间组;将临时表空间组的最后一个临时表空间删除时,自动删除临时表空间组。
使用临时表空间组的好处有:
⊙ 同一个用户在不同的session里可以同时使用不同的临时表空间;
⊙ 并行操作中,不同的从属进程可以使用不同的临时表空间;
⊙ 在数据库层面可以同时指定多个默认临时表空间。
创建临时表空间组时,可以使用Database Control来实现。如图6-9所示。我们还可以设置数据库的默认临时表空间为一个临时表空间组。就像图6-9中的③部分,只要选中“Set as default temporary group”前的checkbox。
创建临时表空间组可以通过SQL命令完成。既可以在创建临时表空间的同时指定其所属的临时表空间组,也可以在创建完临时表空间以后,再将该临时表空间关联到某临时表空间组上去。
create temporary tablespace temp tempfile '/u01/app/oracle/oradata/ora10g/temp01.dbf' size 100M autoextend on tablespace group temp_grp; --创建临时表空间时指定其所属临时表空间组 alter tablespace temp1 tablespace group temp_grp; --将某个已经创建好的临时表空间关联组 alter tablespace temp tablespace group ‘’; --将临时表空间从临时表空间组里移出 alter database default temporary tablespace temp_grp; --设置数据库默认临时表空间为一个组
临时表空间组的信息可以从数据字典dba_tablespace_groups里获取。
图6-9 管理临时表空间组
6.1.4 非默认数据块大小的表空间
在Oracle 9i之前,Oracle的表空间只支持一种尺寸的数据块,而从Oracle 9i开始,可以支持不同尺寸的表空间。这是因为,在OLTP应用中,事务都倾向于短小、涉及的数据比较少,因此建议使用较小的数据块,一般最大不超过8KB。而在DSS或数据仓库应用中,事务都比较大,涉及的数据量也很大,因此建议使用较大的数据块,比如16KB或32KB。但是,很多系统都是混合型的,白天为OLTP应用,晚上进行批处理、生成汇总报表等具有DSS特征的应用。这时,我们就可以利用多尺寸数据块的特性:为OLTP应用所在的表空间设置4KB或8KB大小的数据块;而为DSS或数据仓库应用所在的表空间设置16KB或32KB大小的数据块。
Oracle 9i以后,当然包括Oracle 10g,数据库总共可以支持5种尺寸的数据块:2KB、4KB、8KB、16KB、32KB。我们在其中选择一种作为标准数据块大小,另外4种作为非标准数据块大小。通过定义初始化参数db_block_size来定义标准块大小,该参数只能在创建数据库时指定,创建完数据库以后不能修改。系统表空间和临时表空间必须使用标准块大小,可以对undo表空间指定非标准块大小。标准块所在的buffer cache由初始化参数db_cache_size指定。
如果我们要创建其他非标准块大小的表空间,则必须先设定非标准块所在的buffer cache,包括5个初始化参数:db_2k_cache_size(存放2KB大小的数据块)、db_4k_cache_size(存放4KB大小的数据块)、db_8k_cache_size(存放8KB大小的数据块)、db_16k_cache_size(存放16KB大小的数据块)、db_32k_cache_size(存放32KB大小的数据块)。这些参数我们通常也简称为db_Nk_cache_size。如果我们设定了标准块大小尺寸为8KB,则不能再次指定db_8k_cache_size的大小。
在指定了db_Nk_cache_size以后,就可以创建非标准块的表空间了。比如,我们指定了db_16k_cache_size为50MB,然后创建一个16KB大小的数据块的表空间,其SQL语法为:
create tablespace nk_tbs datafile '/u01/app/oracle/ordata/ora10g/nk_tbs01.db' size 10M blocksize 16K;
该命令中的关键字blocksize说明了表空间的数据块大小。