ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 再说HWM(下)

再说HWM(下)

原创 Linux操作系统 作者:realkid4 时间:2011-09-15 21:26:17 0 删除 编辑

 

本篇继续讨论HWM的影响和处理。

 

3、HWM对系统的影响

 

HWM是Oracle标记数据表曾经使用过的最多数据块位置。同水库中标记历史最高水位一样,HWM只是表示曾经使用过usable和从未使用过unusable数据块之前的分界。

 

在堆表(Heap Table)的情况下,每次普通的insert操作是不一定推动HWM移动的。因为Heap Table的随机存储机制,使得在HWM下,可能存在很多的空闲空间。默认情况下的insert操作,Oracle是会优先插入这些空闲空间,以后才会推高HWM。

 

对一般情况下,我们遇到HWM相关的影响只有一种,就是超高水位线数据表中数据量很少的情况。我们经常听到开发或者运维人员抱怨:“一张数据表,其中的数据没有几条,或者根本就是空表,但是select一下超慢无比”。

 

这种情况下,一般就可以考虑是由于HWM过高引起的问题。我们访问数据表大都是两个方式:Full Table Scan或者Access Table by rowid。两种方式下,Oracle的行为完全不同。

 

ü        Access Table by rowid,是Oracle根据数据行记录的物理地址进行精确定位。Rowid是Oracle物理地址表述,包括文件号、对象号、块号和块中slot编号。这种方式被认为是目前最快定位数据行的方式;

ü        Full Table Scan,也就是我们常说的全表扫描。Oracle处理FTS的流程是:先从数据字典表中获取到数据段头segment header块位置,读取其中的信息。段头块中就包括了该数据段所属的extent分配使用情况,以及HWM位置。根据这些信息,Oracle会逐个块的读取分配extents下的所有使用过的block。不管该块是否已经空闲,直到读取到HWM位置;

 

Access table by rowid是与HWM无关的操作访问类型。而FTS全表扫描的时候是受到HWM严重影响的。如果该数据表曾经很大,现在数据量很小,那么进行FTS的话,速度是很慢的。

 

 

SQL> set timing on;

SQL> explain plan for select count(*) from t;

Explained

 

Executed in 0.047 seconds

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

Plan hash value: 2966233522

-------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |

-------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |   166   (1)| 00:00:02 |

|   1 |  SORT AGGREGATE    |      |     1 |            |          |

|   2 |   TABLE ACCESS FULL| T    |     1 |   166   (1)| 00:00:02 |

-------------------------------------------------------------------

 

9 rows selected

 

Executed in 0.359 seconds

 

 

证明select count(*) from t执行FTS路径。

 

//当一个extent分配时;

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

  COUNT(*)

----------

         1

 

SQL> select count(*) from t;

 

  COUNT(*)

----------

         0

 

Executed in 0 seconds

 

//经过一系列添加后删除,分配出38个数据extents.

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

  COUNT(*)

----------

        38

 

Executed in 0.125 seconds

 

SQL> select count(*) from t;

 

  COUNT(*)

----------

         0

 

Executed in 0.016 seconds

 

 

可见,过高或者失控的HWM可能会引起一些性能问题。那么,在讨论如何处理过高HWM之前,我们先讨论下怎么看待HWM。笔者有如下观点:

 

首先,一般情况下的数据表,特别是OLTP系统,HWM在生产运行一段时间之后是维持在相对稳定的情况下。对online数据表而言,要控制累计数据和不活跃数据的数据量,就需要主动进行归档功能,来转移过期数据。所以,online数据表的数据量是可以维持在一个业务可预测的程度的,从而HWM出现一味上升的可能性不大。一般数据表的HWM应该是可以维持在一个稳定程度的。

 

如果出现HWM一味升高,频繁引起问题的情况,可以认为是两种可能。首先是系统可能就没有考虑到数据归档的情况,一味的增加online数据表,最终会引发整体的关键业务性能问题。另一种是数据表存在数据删除归档功能,但是在加载操作时,过多不合理的使用direct load方式加载数据,一味推高HWM。之后的归档又将HWM下的数据删除。这样就需要进行重新设计调整。

 

那么,有没有数据表HWM只增加,数据只增加不减少。我们认为通常生产环境下这种情况是很少的,而且无论是从系统设计规划还是运维管理上,这都是不合理的。数据是有优先级别的,一些老旧数据尽可能的分离出online关键业务,可以设置专门的查询模块。同时,对一些历史表,也不是一味的增加,在一些期限之后也要考虑使用磁带进行offline处理。

 

 

4、处理HWM问题的方法

 

最后我们讨论一下出现HWM之后,如何进行处理。HWM问题主要在于堆表内部空间空间过多,所以解决的核心在于将数据进行重排,“压紧”数据行。目前处理这种问题的方法有三个。

 

ü        Truncate 数据表

 

HWM下调的解决是让数据段segment“交还”回分配的空间。Truncate是一个DDL语句,相当于将数据段重新构建。具体处理上,可以先将数据保存在一个备份表中,之后truncate目标数据表,再将备份数据还原。

 

 

SQL> select count(*) from t;

  COUNT(*)

----------

         9

 

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

  COUNT(*)

----------

        38

 

SQL> create table t_bak as select * from t;

Table created

 

SQL> truncate table t;

Table truncated

 

Executed in 0.125 seconds

 

SQL> insert into t select * from t_bak;

9 rows inserted

 

SQL> commit;

Commit complete

 

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

  COUNT(*)

----------

         1

 

Executed in 0.11 seconds

 

数据段从38个分区,下降为1个分区。

 

ü        Move方式调整数据行

 

Move是对数据表进行表空间移动的命令,我们也可以使用该命令进行数据表HWM收缩操作。Move命令的效果是将数据表行记录进行移动,所以可以将分散的数据行加以整理。

 

 

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

  COUNT(*)

----------

        21

 

SQL> create index idx_t_id on t(object_id);

Index created

 

--此时其他会话insert数据,该数据表有行共享锁;

SQL> alter table t move;

alter table t move

 

ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源

 

SQL> alter table t move;

 

Table altered

 

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

 

  COUNT(*)

----------

        19

 

 

注意上面的代码段,提示资源繁忙。说明Move操作会以独占的方式持数据表锁,在进行move的时候是不允许其他会话进行DML/DDL操作的。此时,我们查看T上索引的情况。

 

 

SQL> select index_name,STATUS from dba_indexes where index_name='IDX_T_ID' and wner='SYS';

 

INDEX_NAME                     STATUS

------------------------------ --------

IDX_T_ID                       UNUSABLE

 

SQL> alter index idx_t_id rebuild;

 

Index altered

 

SQL> select index_name,STATUS from dba_indexes where index_name='IDX_T_ID' and wner='SYS';

 

INDEX_NAME                     STATUS

------------------------------ --------

IDX_T_ID                       VALID

 

 

可见这是一个move命令的注意点,由于move会引起数据行的变化,从而对应的数据行rowid也会发生变化。保存rowid在叶子节点上的索引也就随时失效,需要DBA手工的进行rebuild操作。

 

此外,move命令还有一个问题就是空间使用,要求在表空间上有额外的空间供使用。

 

ü        Shrink space ASSM下的新手段

 

进入Oracle 9i之后,推出了ASSM(Automatic Segment Space Management)特性。到了10g之后,随之推出了shrink space功能,可以进行HWM收缩操作。

 

注意,shrink space使用是需要表空间使用ASSM管理方式,同时要开启数据表row movement功能。

 

 

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

 

  COUNT(*)

----------

        21

 

--第一次尝试shrink space

SQL> alter table t shrink space;

alter table t shrink space

 

ORA-10636: ROW MOVEMENT is not enabled

 

SQL> alter table t enable row movement;

 

Table altered

 

SQL> alter table t shrink space;

Table altered

 

SQL> select count(*) from dba_extents where wner='SYS' and segment_name='T';

 

  COUNT(*)

----------

        18

 

SQL> select index_name,STATUS from dba_indexes where index_name='IDX_T_ID' and wner='SYS';

 

INDEX_NAME                     STATUS

------------------------------ --------

IDX_T_ID                       VALID

 

 

使用shrink space,基本可以消除move操作带来的问题,如索引手工重建等。简单的说,shrink space是一个两步走操作:第一步是将数据行整理压实,第二步是下调水位线HWM。

 

通过不同的控制参数,我们是可以控制shrink space的操作步骤的。使用shrink space compact可以让Oracle只进行数据行压实,不继续HWM下调。

 

 

SQL> alter table t shrink space compact;

 

Table altered

 

 

 

5、结论

 

Oracle HWM是一个从存储角度对Oracle行为分析的重要内容,可以帮助我们了解Oracle在处理空间分配和使用时的规则。

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/17203031/viewspace-707621/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 再说HWM(上)
请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    8039926