使用在线段收缩(ONLINESEGMENTSHRINK)回收浪费的段空间

   ONLINE TABLE REDEFINITION(在线重定义表)(详见:《使用DBMS_REDEFINITION包执行在线重定义表(ONLINE TABLE REDEFINITION) 》:http://blog.itpub.net/23135684/viewspace-1765128/)也可以完成数据空间的回收,但是ONLINE SEGMENT SHRINK更合适单纯的表空间回收,这篇文章将根据官方文档的内容讨论通过在线段收缩回收浪费的空间。

一.回收未使用空间的原理

    随着时间的推移,针对表空间下对象的UPDATE和DELETE操作会产生个别空的空间,这些空间不是足够的大,没办法被新插入的数据使用。这种类型的空空间被认为是自由空间的碎片。

    拥有自由空间碎片的对象存在空间的浪费,也会影响数据库的性能。首选的碎片整理和空间的回收方法是执行在线段收缩(online segment shrink),这个过程会将高水位线以下的自由空间的碎片整合到一起,把段压紧,压紧之后,高水位线可以移动,最终的结果是新的自由空间在高水位线以上,高水位线以上的空间之后会回收(deallocated),在整个在线段回收的操作过程中段仍然可以被查询和执行DML操作,并且没有额外的磁盘空间需要被分配。

    使用Segment Advisor标示段是在线段回收的优势,只有段属于本地表空间管理和ASSM才是可行的。
如果段不符合在线段回收的要求,或者你想在回收空间的过程中改变表的逻辑或者物理属性,可以使用在线表重定义的方式来实现段的空间回收。在线重定义被认为是重新对表的组织,和在线段回收不同,它要求分配额外的磁盘空间。

注意:SHRINK和DEALLOCATE两个操作是有区别的,SHRINK是碎片整理,DEALLOCATE是降低高水位线,下面会对这两个的区别进一步的说明。

二.Segment Advisor

   Segment Advisor用来鉴别Segment空间回收是否是可行的。它通过检查使用情况,在AWR中的增长统计信息,以及段中的样例数据来进行分析。Segment Advisor被配置成在维护窗口期间自动运行的维护任务,当然也可以手动运行它。Segment Advisor自动维护认为被叫做Automatic Segment Advisor。

Segment Advisor生成以下的建议:
1).Segment Advisor决定一个对象是否有重大的自由空间,推荐执行在线段SHRINK。如果对象对应的表不符合回收条件,Segment Advisor推荐在线表重定义。
2).Segment Advisor决定表能从压缩或者OLTP压缩中获得优势,推荐使用这种方法。
3).Segment Advisor遇到表row chain超过阀值,它记录表大量chain row这种情况。

如果收到空间管理告警,或者你想回收空间,应该从Segment Advisor开始。

Automatic Segment Advisor不是分析数据库的每一个对象,而是审查数据库统计信息,段数据采样,然后选择一下的对象进行分析:
>表空间超过临界点,或者空间阀值告警。
>最活跃的段。
>最高增长率的段。

Segment Advisor也手动的调用,可以通过OEM和DBMS_ADVISOR包进行调用。这里我们讨论通过DBMS_ADVISOR进行调用的方法。

使用DBMS_ADVISOR包的存储过程创建Segment Advisor工作,设置工作的属性,然后执行这个工作。使用此包必须有ADVISOR的权限。

下面通过一个例子来讨论通过DBMS_ADVISOR手动调用Segment Advisor的方法,用户执行DBMS_ADVISOR包的存储过程必须用此包的EXECUTE对象权限,或者ADVISOR系统权限。

注意:如果通过DBMS_ADVISOR.CREATE_OBJECT对表进行操作,如果表是一个分区表,Segment Advisor分析表的所有分区,针对每个分区生成单独的findings和推荐。

variable id number;
begin
  declare
  name varchar2(100);
  descr varchar2(500);
  obj_id number;
  begin
  name:='Manual_Employees';
  descr:='Segment Advisor Example';

  dbms_advisor.create_task (
    advisor_name     => 'Segment Advisor',
    task_id          => :id,
    task_name        => name,
    task_desc        => descr);

  dbms_advisor.create_object (
    task_name        => name,
    object_type      => 'TABLE',
    attr1            => 'HR',
    attr2            => 'EMPLOYEES',
    attr3            => NULL,
    attr4            => NULL,
    attr5            => NULL,
    object_id        => obj_id);

  dbms_advisor.set_task_parameter(
    task_name        => name,
    parameter        => 'recommend_all',
    value            => 'TRUE');

  dbms_advisor.execute_task(name);
  end;
end; 
/

查看Segment Advisor的结果
Segment Advisor创建了几种类型的结果,recommendations,findings,actions和objects。


方法1:通过DBMS_SPACE.ASA_RECOMMENDATIONS查看结果。
这是一种最简单的方法。

select tablespace_name, segment_name, segment_type, partition_name,
recommendations, c1 from
table(dbms_space.asa_recommendations('FALSE', 'FALSE', 'FALSE'));


TABLESPACE_NAME                SEGMENT_NAME                   SEGMENT_TYPE
------------------------------ ------------------------------ --------------
PARTITION_NAME
------------------------------
RECOMMENDATIONS
-----------------------------------------------------------------------------
C1
-----------------------------------------------------------------------------
TVMDS_ASSM                     ORDERS1                        TABLE PARTITION
ORDERS1_P2
Perform shrink, estimated savings is 57666422 bytes.
alter table "STEVE"."ORDERS1" modify partition "ORDERS1_P2" shrink space
 
TVMDS_ASSM                     ORDERS1                        TABLE PARTITION
ORDERS1_P1
Perform shrink, estimated savings is 45083514 bytes.
alter table "STEVE"."ORDERS1" modify partition "ORDERS1_P1" shrink space
 
TVMDS_ASSM_NEW                 ORDERS_NEW                     TABLE
 
Perform shrink, estimated savings is 155398992 bytes.
alter table "STEVE"."ORDERS_NEW" shrink space
 
TVMDS_ASSM_NEW                 ORDERS_NEW_INDEX               INDEX
 
Perform shrink, estimated savings is 102759445 bytes.
alter index "STEVE"."ORDERS_NEW_INDEX" shrink space


方法2:通过查询DBA_ADVISOR_*视图可以获得结果。

在查询DBA_ADVISOR_*视图之前,可以通过查询DBA_ADVISOR_TASKS.STATUS字段确保Segment Advisor工作已经结束。

select task_name, status from dba_advisor_tasks
   where owner = 'STEVE' and advisor_name = 'Segment Advisor';
 
TASK_NAME                      STATUS
------------------------------ -----------
Manual Employees               COMPLETED

以下的例子说明如何查询DBA_ADVISOR_*视图从所有运行的Segment Advisor中检索通过STEVE用户提交的工作:
select af.task_name, ao.attr2 segname, ao.attr3 partition, ao.type, af.message 
  from dba_advisor_findings af, dba_advisor_objects ao
  where ao.task_id = af.task_id
  and ao.object_id = af.object_id
  and ao.owner = 'STEVE';
TASK_NAME          SEGNAME      PARTITION       TYPE             MESSAGE
------------------ ------------ --------------- ---------------- --------------------------
Manual_Employees   EMPLOYEES                    TABLE            The free space in the obje
                                                                 ct is less than 10MB.
 
Manual_Salestable4 SALESTABLE4  SALESTABLE4_P1  TABLE PARTITION  Perform shrink, estimated
                                                                 savings is 74444154 bytes.
 
Manual_Salestable4 SALESTABLE4  SALESTABLE4_P2  TABLE PARTITION  The free space in the obje
                                                                 ct is less than 10MB.


三.在线段空间SHRINK

   段SHRINK是在线的,内部操作。在段SHRINK阶段数据的移动不会影响DML操作和查询操作。并行的DML操作在SHRINK操作结束,空间deallocated的时候会被短时间的阻塞。在SHRINK操作期间索引会被维护,操作完成后仍然是可用的。Segment SHRINK不要求额外的空间分配。

    Segment SHRINK高水位线以上和以下未使用的空间,相比较,空间deallocation只回收高水位线以上的空间。在回收操作中,默认情况下,数据库压紧段,调整高水位线,释放浪费的空间。

    Segment Shrink要求行被移动到新的位置,因此必须在你想要shrink的独享上首先启用行迁移,和禁用在对象上基于rowid的触发器定义。通过ALTER TABLE ... ENABLE ROW MOVEMENT语句启用行迁移。

shrink只支持本地化表空间管理和ASMM管理的表空间下的表。

可以在表,IOT表,索引,分区,子分区,物化视图,物化视图日志上shrink空间。

如果表上有基于函数的索引,那么将无法对表进行shrink操作(CASCADE和NOCASCADE都不行)。

两个shrink字句用于控制如何来shrink操作:

>COMPACT划分SHRINK段操作到两个阶段,当你指定COMPACT,Oracle数据库整理段空间碎片,压紧表行,但是重新设置高水位线和deallocation空间会被延期。这个对长时间运行的查询可能读取被回收的块来说是有用的。这个碎片整理和压紧的结果会被保留到磁盘,之后可以再次以没有COMPACT字句的命令执行SHRINK SPACE语句。

>CASCADE字句延伸段shrink操作到所有依赖段的对象,例如,当SHRINK表段的时候指定CASCADE,表相关的所有索引将被SHRINK(不需要在SHRINK分区表的分区的时候指定CASCADE),可以运行DBMS_SPACE.OBJECT_DEPENDENT_SEGMENTS存储过程来查看依赖段的所有对象。

如果不指定COMPAT字句,执行段SHRINK之后的SQL语句都将因为失效的游标被重新的解析,因为这是个DDL操作。

例子:

>Shrink表和所有依赖它的段:(包括BASICFILE LOB段):
ALTER TABLE employees SHRINK SPACE CASCADE;

>只Shrink BASICFILE LOB段:
ALTER TABLE employees MODIFY LOB (perf_review) (SHRINK SPACE);

>Shrink分区表的单一分区:
ALTER TABLE customers MODIFY PARTITION cust_P1 SHRINK SPACE;

>Shrink IOT索引段和overflow段:
ALTER TABLE cities SHRINK SPACE CASCADE;

>只SHRINK IOT overflow段:
ALTER TABLE cities OVERFLOW SHRINK SPACE;

四.Deallocate未使用的空间

   当执行deallocate未使用的空间,数据库使得数据库段结尾之后未使用的空间变得可用(降低高水位线),注意,在对表做SHRINK之后高水位线默认会被降低,DEALLOCATE用于未执行SHRINK或者,非默认的SHRINK时使用。

执行deallocation之前,可以运行DBMS_SPACE.UNUSED_SPACE过程将返回高水位线位置信息,和段空间未使用空间的总数。对于本地化和段自动化管理的表空间,SPACE_USAGE可以获得更准确的数据。

以下的语句deallocate段未使用的空间(表,索引或者cluster):
ALTER TABLE table DEALLOCATE UNUSED KEEP ;
ALTER INDEX index DEALLOCATE UNUSED KEEP ;
ALTER CLUSTER cluster DEALLOCATE UNUSED KEEP ;

KEEP是可选的字句,指定段保留的空间总数,可以通过检查DBA_FREE_SPACE视图验证DEALLOCATED为自由的空间。

相关文章:
   《Moving表到新的段或者表空间》:http://blog.itpub.net/23135684/viewspace-1766480/

--end--


文章标题:使用在线段收缩(ONLINESEGMENTSHRINK)回收浪费的段空间
标题来源:http://ybzwz.com/article/josocd.html