Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48999
  • 博文数量: 29
  • 博客积分: 2016
  • 博客等级: 大尉
  • 技术积分: 320
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-23 14:27
文章分类

全部博文(29)

文章存档

2010年(29)

我的朋友

分类: Oracle

2010-09-23 15:13:53

说到HWM,我们首先要简要的谈谈ORACLE的逻辑存储管理.我们知道,ORACLE在逻辑存储上分4个粒度:表空间,段,区和块.
(1)块:是粒度最小的存储单位,现在标准的块大小是8K,ORACLE每一次I/O操作也是按块来操作的,也就是说当ORACLE从数据文件读数据时,是读取多少个块,而不是多少行.
(2)区:由一系列相邻的块而组成,这也是ORACLE空间分配的基本单位,举个例子来说,当我们创建一个表PM_USER时,首先ORACLE会分配一区的空间给这个表,随着不断的INSERT数据到
   PM_USER,原来的这个区容不下插入的数据时,ORACLE是以区为单位进行扩展的,也就是说再分配多少个区给PM_USER,而不是多少个块.
(3)段:是由一系列的区所组成,一般来说,当创建一个对象时(表,索引),就会分配一个段给这个对象.所以从某种意义上来说,段就是某种特定的数据.如CREATE TABLE PM_USER,这个段就
   是数据段,而CREATE INDEX ON PM_USER(NAME),ORACLE同样会分配一个段给这个索引,但这是一个索引段了.查询段的信息可以通过数据字典: SELECT * FROM USER_SEGMENTS来获得,
(4)表空间:包含段,区及块.表空间的数据物理上储存在其所在的数据文件中.一个数据库至少要有一个表空间.
OK,我们现在回到HWM上来,那么,什么是高水位标记呢?这就跟ORACLE的段空间管理相关了.
(一)ORACLE用HWM来界定一个段中使用的块和未使用的块.
    举个例子来说,当我们创建一个表:PT_SCHE_DETAIL时,ORACLE就会为这个对象分配一个段.在这个段中,即使我们未插入任何记录,也至少有一个区被分配,第一个区的第一个块就称
    为段头(SEGMENT HEADE),段头中就储存了一些信息,基中HWM的信息就存储在此.此时,因为第一个区的第一块用于存储段头的一些信息,虽然没有存储任何实际的记录,但也算是被使
    用,此时HWM是位于第2个块.当我们不断插入数据到PM_USER后,第1个块已经放不下后面新插入的数据,此时,ORACLE将高水位之上的块用于存储新增数据,同时,HWM本身也向上移.也
    就是说,当我们不断插入数据时,HWM会往不断上移,这样,在HWM之下的,就表示使用过的块,HWM之上的就表示已分配但从未使用过的块.
(二)HWM在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会往下移.
    这就好比是水库的水位,当涨水时,水位往上移,当水退出后,最高水位的痕迹还是清淅可见.
    考虑让我们看一个段,如一张表,其中填满了块,所有快空间是满的,在正常操作过程中,删除了一些行,就出现一些空的块,因此,现有就有了许多浪费的空间:(I) 在表的上
    一个末端和现有的块之间,以及 (II) 在块内部,其中还有一些没有删除的行。  
    ORACLE 不会释放空间以供其他对象使用,有一条简单的理由:由于空间是为新插入的行保留的,并且要适应现有行的增长。被占用的最高空间称为最高使用标记 (HWM)。
三)HWM的信息存储在段头当中.
   HWM本身的信息是储存在段头.在段空间是手工管理方式时,ORACLE是通过FREELIST(一个单向链表)来管理段内的空间分配.在段空间是自动管理方式时(ASSM),ORACLE是通过BITMAP来
   管理段内的空间分配.
(四)ORACLE的全表扫描是读取高水位标记(HWM)以下的所有块.
   所以问题就产生了.当用户发出一个全表扫描时,ORACLE 始终必须从段一直扫描到 HWM,即使它什么也没有发现。该任务延长了全表扫描的时间。
(五)当用直接路径插入行时 — 例如,通过直接加载插入(用 APPEND 提示插入)或通过 SQL*LOADER 直接路径 — 数据块直接置于 HWM 之上。它下面的空间就浪费掉了。
我们来分析这两个问题,后者只是带来空间的浪费,但前者不仅是空间的浪费,而且会带来严重的性能问题.我们来看看下面的例子:
(A)我们先来搭建测试的环境,第一步先创建一个段空间为手工管理的表空间:
-------------------------------------------------------------------------------------------------------------------------------
PCTUSED与PCTFREE:
  PCTFREE:块中保留用于UPDATE操作的空间百分比,当数据占用的空间达到此上限时,新的数据将不能再插入到此块 中;
 PCTUSED:指定块中数据使用空间的最低百分比;当一个块在达到PCTFREE,之后经历了一些DELETE操作,在其空间使用下降到PCTUSED 后便可以重新被用于INSERT数据;这就是
  PCTFREE/PCTUSED参数的含义;
  调整PCTFREE、PCTUSED参数的目标一方面是提高性能,另一方面则主要是提高空间使用效率,避免出现块中存在有许多未用的空间,但却无法找到一 个块可以被用于插入新数据
    行的情况发生。
 PCTFREE的使用
  在Oracle中表的每一行数据由唯一的ROWID标记;而Oracle支持的数据类型中有一些长度是可变的,如VARCHAR,当对 这些数据进行UPDATE时,如果块中的可用空间不能容纳
    UPDATE后的数据行时,Oracle将会把此行移到其它数据块,同时保留此数据行的 ROWID不变,并在原有块中建一指针指向行迁移后的位置。在这种情况下读取一行数据将需要访问
    2个数据块,从而导致性能下降。PCTFREE保留的空间 就是为确保更改后的数据行可以仍存放于原有数据块中,避免行迁移的情况发生。 由此,如果PCTFREE设置不足时可能产生行
    迁移;而另一方面如果PCTFREE设置过高,将会造成空间浪费。因此正确设置PCTFREE需要对表中数 据的使用进行分析。对于数据长度不会变化或极少更新的情况,可以采用较小
    的PCTFREE;对于其它大多数情况应采用稍大的 PCTFREE(PCTFREE的缺省值是10,如果不好估计需预留的空间,可以使用15-25的范围),不要为节约块中的空间而使用较小的
    PCTFREE值。
 PCTUSED的使用
  当块的使用的空间下降到PCTUSED后,此块被重新放回空闲链表(Freelist) 中,作为后续Insert的候选块。同样,设置PCTUSED需要视数据行的特性和Insert、Update、Delete
    的模式而定,但必须遵守的原 则是:db_block_size * (100 - PCTFREE - PCTUSED)必须比行的长度大。 对于数据行长度变化较大的情况,应使用最大行长度来计算PCTUSED,并
    且应使用较低的PCTUSED值。因为在执行Insert时,如果数据块的可用 空间不能装下一行数据,当块的使用的空间是在PCTUSED之上,Oracle将把此块从Freelist中移走;当块的
    使用的空间是在PCTUSED之 下,Oracle将会扩展段空间。因此,PCTUSED如果设得过高,将导致段的不断扩展。 当数据行长度不大时,使用缺省的PCTUSED(40)是比较合适的;
    对于行长度较大的情况,最长的行有可能会占用半个以上的块空间,此时可设置 PCTUSED为10。较小的PCTUSED仅在表中的数据以随机方式被删除,而且仍有一些行长时间保留在
    块中时,才会造成空间使用上的问题,因为这些块 可能需要较长的时间才能或永远不能重新被用于存放新数据。在这种应用中,如果空间利用率一直处于较低水平,则需对
    PCTUSED进行分析和调整。
  pctfree参数是控制freelist un-links的(即将块由freelists中移除)。设置pctfree=10 意味着每个块都保留10%的空间用作行扩展。pctused参数是控制freelist re-links
    的。设置pctused=40意味着只有在块的使用低于40%时才会回到表格的freelists中。
  PCTFREE和PCTUSED的概念:PCTFREE存储参数告诉ORACLE什么时候应该将数据块从对象的空闲列表中移出。ORACLE的默认参数是 PCTFREE=10;也就是说,一旦一个INSERT操作使得
    数据块的90%被使用,这个数据块就从空闲列表(free list)中移出。 PCTUSED存储参数告诉ORACLE什么时候将以前满的数据块加到空闲列表中。当记录从数据表中删除时,数据库
    的数据块就有空间接受新的记录,但只有当填充的空间降到PCTUSED值以下时,该数据块才被连接到空闲列表中,才可 以往其中插入数据。PCTUSED的默认值是PCTUSED=40。
    (1)PCTUSED较高意味着相对较满的数据块会被放置到空闲列表中,从而有效的重复使用数据块的空间,但会导致I/O消耗。PCTUSED低意味着在 一个数据块快空的时候才被放置
    到空闲列表中,数据块一次能接受很多的记录,因此可以减少I/O消耗,提高性能。
   (2)PCTFREE的值较大意味着数据块没有被利用多少就从空闲列表中断开连接,不利于数据块的充分使用。PCTFREE过小的结果是,在更新时可能会 出现数据记录迁移(Migration)
    的情况。(注:数据记录迁移(Migration)是指记录在是UPDATE操作扩展了一个VARCHAR2类型 的列或BLOB列后,PCTFREE参数所指定的空间不够扩展,从而记录被ORACLE强制迁移到
    新的数据块,发生这种情况将较严重的影响ORACLE的 性能,出现更新缓慢)。
------------------------------------------------------------------------------------------------------------------------------------------
Oracle数据库中的段管理方式详细介绍
  
关键字: 触发器语法 Oracle物化视图 跟踪sql语句 密码丢失 数据仓储 Oracle 9i个人版
本文详细介绍Oracle数据库中的段管理方式详细介绍
  用 Oracle 数据库 10g 通过回收浪费的空间、联机重组表格和评估增长的趋势,有效地在段中进行存储管理。近来,有人要求我评估一个与 Oracle 数据库竞争的 RDBMS。在供应商的演示过程中,观众认为“最棒”的特性是,对联机重组的支持 — 该产品可以联机重新部署数据块,以使段的等价物更简洁,并且不会影响当前的用户。
  那时,Oracle 还没有在 Oracle9i 数据库中提供这种功能。但是现在,有了 Oracle 数据库 10g,就可以轻松地联机回收浪费的空间和压缩对象—正好适合于起步者。
  不过,在检验该特性之前,让我们看一看处理这项任务的“传统的”方法。
  当前惯例
  考虑让我们看一个段,如一张表,其中填满了块,如图 1 所示。在正常操作过程中,删除了一些行,如图 2 所示。现有就有了许多浪费的空间:(i) 在表的上一个末端和现有的块之间,以及 (ii) 在块内部,其中还有一些没有删除的行。

   
  图 1:分配给该表的块。用灰色正方形表示行
  Oracle 不会释放空间以供其他对象使用,有一条简单的理由:由于空间是为新插入的行保留的,并且要适应现有行的增长。被占用的最高空间称为最高使用标记 (HWM),如图 2 所示。

  图 2:行后面的块已经删除了;HWM 仍保持不变
  但是,这种方法有两个主要的问题:
  当用户发出一个全表扫描时,Oracle 始终必须从段一直扫描到 HWM,即使它什么也没有发现。该任务延长了全表扫描的时间。
关键字: 触发器语法 Oracle物化视图 跟踪sql语句 密码丢失 数据仓储 Oracle 9i个人版
本文详细介绍Oracle数据库中的段管理方式详细介绍
  当用直接路径插入行时 — 例如,通过直接加载插入(用 APPEND 提示插入)或通过 SQL*Loader 直接路径 — 数据块直接置于 HWM 之上。它下面的空间就浪费掉了。
  在 Oracle9i 及其以前的版本中,可以通过删除表,然后重建表并重新加载数据来回收空间;或通过使用 ALTER TABLE MOVE 命令把表移动到一个不同的表空间中来回收空间。这两种处理方式都必须脱机进行。另外,可以使用联机表重组特性,但是这需要至少双倍的现有表空间。
  在 10g中,该任务已经变得微不足道了;假如您的表空间中支持自动段空间管理 (ASSM),您现在可以缩小段、表和索引,以回收空闲块并把它们提供给数据库以作他用,让我们看看其中的缘由。
  10g 中的段管理方式
  设想有一个表 BOOKINGS,它保存有经由 Web 站点的联机登记。当一个登记确认后,就会把它存储在一个存档表 BOOKINGS_HIST 中,并从 BOOKINGS 表中删除该行。登记和确认之间的时间间隔依据客户有很大的不同,由于无法从删除的行获得足够的空间,因此许多行就插入到了表的 HWM 之上。
  现在您需要回收浪费的空间。首先,准确地查明在可回收的段中浪费了多少空间。由于它是在支持 ASSM 的表空间中,您将不得不使用 DBMS_SPACE 包的 SPACE_USAGE 过程,如下所示:
  declare  
  l_fs1_bytes number;
  l_fs2_bytes number;
  l_fs3_bytes number;
  l_fs4_bytes number;
  l_fs1_blocks number;
  l_fs2_blocks number;
  l_fs3_blocks number;
  l_fs4_blocks number;
  l_full_bytes number;
  l_full_blocks number;
  l_unformatted_bytes number;
  l_unformatted_blocks number;
  begin
  dbms_space.space_usage(
  segment_owner   => user,
  segment_name    => 'BOOKINGS',
  segment_type    => 'TABLE',
  fs1_bytes     => l_fs1_bytes,
  fs1_blocks     => l_fs1_blocks,
  fs2_bytes     => l_fs2_bytes,
  fs2_blocks     => l_fs2_blocks,
  fs3_bytes     => l_fs3_bytes,
  fs3_blocks     => l_fs3_blocks,
  fs4_bytes     => l_fs4_bytes,
  fs4_blocks     => l_fs4_blocks,
  full_bytes     => l_full_bytes,
  full_blocks    => l_full_blocks,
  unformatted_blocks => l_unformatted_blocks,
  unformatted_bytes => l_unformatted_bytes
  );
  dbms_output.put_line(' FS1 Blocks = '
  ||l_fs1_blocks||' Bytes = '||l_fs1_bytes);
  dbms_output.put_line(' FS2 Blocks = '
  ||l_fs2_blocks||' Bytes = '||l_fs1_bytes);
  dbms_output.put_line(' FS3 Blocks = '
  ||l_fs3_blocks||' Bytes = '||l_fs1_bytes);
  dbms_output.put_line(' FS4 Blocks = '
  ||l_fs4_blocks||' Bytes = '||l_fs1_bytes);
  dbms_output.put_line('Full Blocks = '
  ||l_full_blocks||' Bytes = ||l_full_bytes);
  end;
  /

关键字: 触发器语法 Oracle物化视图 跟踪sql语句 密码丢失 数据仓储 Oracle 9i个人版
本文详细介绍Oracle数据库中的段管理方式详细介绍
  输出结果如下:
  FS1 Blocks = 0 Bytes = 0
  FS2 Blocks = 0 Bytes = 0
  FS3 Blocks = 0 Bytes = 0
  FS4 Blocks = 4148 Bytes = 0
  Full Blocks = 2 Bytes = 16384
  这个输出结果显示有 4,148 个块,具有 75-100% 的空闲空间 (FS4);没有其他空闲块可用。这里仅有两个得到完全使用的块。4,148 个块都可以回收。
  接下来,您必须确保该表支持行移动。如果不支持,您可以使用如下命令来支持它:
  alter table bookings enable row movement;
  或通过 Administration 页上的 企业管理器 10g。您还要确保在该表上禁用所有基于行 id 的触发器,这是因为行将会移动,行 id 可能会发生改变。
  最后,您可以通过以下命令重组该表中现有的行:
  alter table bookings shrink space compact;
  该命令将会在块内重新分配行,如图 3 所示,这就在 HWM 之下产生了更多的空闲块 — 但是 HWM 自身不会进行分配。

  图 3:重组行后的表中的块
  在执行该操作后,让我们看一看空间利用率所发生的改变。使用在第一步展示的 PL/SQL 块,可以看到块现在是如何组织的:
  FS1 Blocks = 0 Bytes = 0
  FS2 Blocks = 0 Bytes = 0
  FS3 Blocks = 1 Bytes = 0
  FS4 Blocks = 0 Bytes = 0
  Full Blocks = 2 Bytes = 16384
  注意这里的重要改变:FS4 块(具有 75-100% 的空闲空间)的数量现在从 4,148 降为 0。我们还看到 FS3 块(具有 50-75% 的空闲空间)的数量从 0 增加到 1。但是,由于 HWM 没有被重置,总的空间利用率仍然是相同的。我们可以用如下命令检查使用的空间:
关键字: 触发器语法 Oracle物化视图 跟踪sql语句 密码丢失 数据仓储 Oracle 9i个人版
本文详细介绍Oracle数据库中的段管理方式详细介绍
  SQL> select blocks from user_segments
  where segment_name = 'BOOKINGS';  
  BLOCKS
  ---------
  4224
  由该表占用的块的数量 (4,224) 仍然是相同的,这是因为并没有把 HWM 从其原始位置移开。可以把 HWM 移动到一个较低的位置,并用如下命令回收空间:
  alter table bookings shrink space;
  注意子句 COMPACT 没有出现。该操作将把未用的块返回给数据库并重置 HWM。可以通过检查分配给表的空间来对其进行测试:
  SQL> select blocks from user_segments
  where segment_name = 'BOOKINGS';  
  BLOCKS
  ----------
  8
  块的数量从 4,224 降为 8;该表内所有未用的空间都返回给表空间,以让其他段使用,如图 4 所示。

  图 4:在收缩后,把空闲块返回给数据库
  这个收缩操作完全是在联机状态下发生的,并且不会对用户产生影响。
  也可以用一条语句来压缩表的索引:
  alter table bookings shrink space cascade;
  联机 shrink 命令是一个用于回收浪费的空间和重置 HWM 的强大的特性。我把后者(重置 HWM)看作该命令最有用的结果,因为它改进了全表扫描的性能。
  找到收缩合适选择
  在执行联机收缩前,用户可能想通过确定能够进行最完全压缩的段,以找出最大的回报。只需简单地使用 dbms_space 包中的内置函数 verify_shrink_candidate。如果段可以收缩到 1,300,000 字节,则可以使用下面的 PL/SQL 代码进行测试:
  begin
  if (dbms_space.verify_shrink_candidate
  ('ARUP','BOOKINGS','TABLE',1300000)
  then
  :x := 'T';
  else
  :x := 'F';
  end if;
  end;
  /

  PL/SQL 过程成功完成。  SQL> print x  
  X
  --------------------------------
  T
  如果目标收缩使用了一个较小的数,如 3,000:
  begin
  if (dbms_space.verify_shrink_candidate
  ('ARUP','BOOKINGS','TABLE',30000)
  then
  :x := 'T';
  else
  :x := 'F';
  end if;
  end;
  变量 x 的值被设置成 'F',意味着表无法收缩到 3,000 字节。现在假定您将着手在一个表上,或者也许是一组表上创建一个索引的任务。除了普通的结构元素,如列和单值性外,您将不得不考虑的最重要的事情是索引的预期大小 — 必须确保表空间有足够的空间来存放新索引。
  在 Oracle 数据库 9i 及其以前的版本中,许多 DBA 使用了大量的工具(从电子数据表到独立程序)来估计将来索引的大小。在 10g中,通过使用 DBMS_SPACE 包,使这项任务变得极其微不足道。

 

阅读(593) | 评论(0) | 转发(0) |
0

上一篇:综合优化

下一篇:协议族

给主人留下些什么吧!~~