暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

表空间管理技术-字典管理表空间

eygle 2019-10-14
656

从图5-2中可以看出,Oracle通过表空间为数据库提供使用空间,那么Oracle必然提供一种技术用于空间管理。


Oracle主要的空间管理方式有两种,一种是Oracle 8i以前的字典管理表空间(DMT)技术,一种就是Oracle 8i以后的本地管理表空间(LMT)技术。由于区间(Extent)是Oracle创建对象时的最小分配单元,所以表空间的管理实际上就是针对于区间的管理。


字典管理表空间


在Oracle 8i以前(不包括8i),只存在一种表空间的管理模式,这就是字典管理表空间(Dictionary Managed Tablespace,简称DMT)。之前创建表空间的主要语法为:

CREATE TABLESPACE tablespace_name
DATAFILE 'datafile_path_name'  [SIZE INTETER [K|M] |[DEFAULT STORAGE]|[PERMANENT|TEMPORARY]]


这里关键字DEFAULT STORAGE指明了该表空间的默认存储格式,包含了INITIAL、NEXT、PCTINCREASE等相关参数的设置。如果在表空间中创建对象(如表、索引等)时不指定存储参数的话,Oracle将采用表空间的存储参数作为对象的默认参数;PERMANENT|TEMPORARY指明了该表空间的类型是永久的还是临时的。


当表空间被创建之后,可以通过查询dba_tablespaces视图来确定表空间的类型:

SQL> select tablespace_name, extent_management,allocation_type
  2  from dba_tablespaces;
TABLESPACE_NAME                EXTENT_MAN ALLOCATIO
------------------------------ ---------- ---------
SYSTEM                         DICTIONARY USER
RBS                            DICTIONARY USER
TEMP                           DICTIONARY USER
USERS                          LOCAL      UNIFORM
4 rows selected.


EXTENT_MANAGEMENT显示为DICTIONARY的就是字典管理表空间。所谓字典管理表空间是指,当创建或删除对象时,Oracle的空间分配或回收是通过数据库中的数据字典表来记录和管理的,用于管理的两个数据字典表分别是:UET$(used extents-已使用的空间)和FET$(free extents-空闲空间)。


可以来简单看一下这两个字典表的结构:

SQL> desc uet$
 名称                                      空?      类型
 ----------------------------------------- -------- ----------------------------
 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
 
SQL> desc fet$
 名称                                      空?      类型
 ----------------------------------------- -------- ----------------------------
 TS#                                       NOT NULL NUMBER
 FILE#                                     NOT NULL NUMBER
 BLOCK#                                    NOT NULL NUMBER
 LENGTH                                    NOT NULL NUMBER


可以清晰地看到,这两个字典表基本上是通过文件号(file#)、数据块号(block#)等信息来管理空间的分配和回收的。


字典管理表空间的工作方式是——当建立一个新的段或者段在表空间中请求新的空间时,Oracle通过执行一系列的SQL语句来完成这个工作,这些工作包括从FET$中找到可用的自由空间,移动或增加相应的行到UET$中,并在FET$中删除相应的记录;当删除一个段的时候,Oracle则移动UET$中相应的行到FET$。


这个过程的发生是连续的、串行的,在繁忙的数据库中,这类操作极可能导致竞争和等待,产生数据字典的争用;另一方面,当数据字典的表的信息被修改时,系统同样要记录undo和redo信息,频繁的修改又不可避免地对整个数据库的性能产生影响。


在繁忙的数据库中,字典管理的表空间可能会成为灾难,下面展示一段Statspack报告,在这个采样周期为1小时的报告中:

DB Name         DB Id    Instance     Inst Num Release     OPS Host
------------ ----------- ------------ -------- ----------- --- ------------
TEAM           2757346   ss7                 1 8.1.7.4.0   NO  db-server
 
                Snap Id     Snap Time      Sessions
                ------- ------------------ --------
 Begin Snap:       2716 28-10月-03 08:15:03      20
   End Snap:       2718 28-10月-03 09:15:31      20
    Elapsed:                  60.47 (mins)


注意到在根据Buffer Gets排序的Top SQL中,有大量的SQL是在进行字典表的空间维护操作,这已经成为了这个数据库的性能瓶颈,下面报告中的SQL语句很好地展示了字典管理表空间的空间维护方式:

  Buffer Gets    Executions  Gets per Exec  % Total  Hash Value
--------------- ------------ -------------- ------- ------------
      4,800,073       10,268          467.5    51.0   2913840444
select length from fet$ where file#=:1 and block#=:2 and ts#=:3
 
        803,187       10,223           78.6     8.5    528349613
delete from uet$ where ts#=:1 and segfile#=:2 and segblock#=:3 a
nd ext#=:4
 
        454,444       10,300           44.1     4.8   1839874543
select file#,block#,length from uet$ where ts#=:1 and segfile#=:
2 and segblock#=:3 and ext#=:4
 
         23,110       10,230            2.3     0.2   3230982141
insert into fet$ (file#,block#,ts#,length) values (:1,:2,:3,:4)
 
         21,201          347           61.1     0.2   1705880752
select file# from file$ where ts#=:1
 
          9,505           12          792.1     0.1   1714733582
select f.file#, f.block#, f.ts#, f.length from fet$ f, ts$ t whe
re t.ts#=f.ts# and t.dflextpct!=0 and t.bitmapped=0
 
          6,426          235           27.3     0.1   1877781575
delete from fet$ where file#=:1 and block#=:2 and ts#=:3
 
          1,267           37           34.2     0.0    904892542
select  file#,block#,length from fet$       where length>=:1 and
 ts#=:2 and file#=:3
 
            901          235            3.8     0.0   3687396716
insert into uet$ (segfile#,segblock#,ext#,ts#,file#,block#,lengt
h)values (:1, :2, :3, :4, :5, :6, :7)


字典管理表空间面临的另外一个严重问题是:空间碎片。


在字典管理表空间中,我们经常会遇到这样的悖论,一个表空间中的自由空间(可以通过dba_free_space视图来计算)还有几百MB,但是一个请求几百KB空间的表可能都已经无法扩展。这是因为表空间中的自由空间并不连续,每块自由空间都很小,已经不能满足一个表的扩展需要,这在Oracle 8的年代常常成为困扰DBA的难题。


在字典管理表空间中,当要满足一个空间要求时,数据库要寻找表空间中的自由空间来使用,如果自由空间大于请求空间,那么自由空间就将被细分,这样将逐渐形成越来越多的离散的、分隔的、小块的自由空间,即空间碎片。

随着时间推移,应用系统的广泛使用,数据中所产生的碎片也会越来越多,这些碎片将对数据库产生以下几点主要影响:


 ·  导致系统性能衰减,如上所述,当要满足一个空间扩展要求时,数据库将首先查找当前最大的自由空间,经过分割,自由空间将逐渐变小,要找到一个满足扩展需求的自由空间已经变得越来越难,从而导致空间分配中的速度问 题。

 ·  大量空间被浪费,尽管有一部分自由空间(如表空间的PCTINCREASE设置为非0值)将会被SMON(系统监控)后台进程周期性地合并,但始终有一部分自由空间无法得以自动合并,从而浪费了大量的宝贵空间,并且非0的PCTINCREASE更容易导致更多的碎片。

 ·  空间释放成为难题,在DMT管理的表空间中,你也许听说过DROP一个大表或删除一个表空间往往要花费数十小时甚至几天的时间,同时会导致严重的性能问题。这是因为当需要删除一个表或表空间时,Oracle同样要维护其空间分配,这样fet$和uet$表同样要被维护,这样的维护耗时将超乎想象。


这里简单地引用一个维护字典管理表空间的案例,以便给大家一些直观的印象。在以下的案例中,我们需要删除一个字典管理的表空间,在删除表空间时,Oracle需要递归地删除表空间里所有的Extent,包括使用的和未使用的。下面以fet$为例,ts#=3的是目标表空间,在fet$中存在44万左右的Extents:

SQL>select ts#,count(*) from fet$ group by ts#;  
       TS#   COUNT(*)
---------- ----------
         0        817
         1      12160
         3     440932
         4      15775
         5       5300
         6     314997  
6 rows selected.


在DROP表空间时,可以反复查询这个视图,根据Extent减少的速度来评估Oracle完成删除所需要的时间。在这个案例中,Oracle每秒仅能清除3个Extent。

那么完成这个操作大约需要40多个小时,可以看到,这个时间消耗是相当惊人的:

SQL> select 440932/3/3600 from dual;  
440932/3/3600
-------------
    40.827037


最终Oracle认识到字典表空间已经成为影响数据库性能的严重问题,于是Oracle在Oracle 8i中开始引入了本地管理表空间(Local Management Tablespace)的技术。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论