HWM&&碎片整理之move操作

针对ASSM segment管理方式的HWM的降法:impdp/expdp,exp/imp,ctas,insert into,move,shrink,在线重定义等方法;
前面已经讨论过在线重定义,impdp/expdp的用法,这里不作讨论,至于ctas,不作讨论;
前面,已经用tom大师的工具来做hwm的判定了;
这里主要说明move用法
move操作:
SQL> create table hwm as select * from dba_objects where 0=1;
Table created.

SQL> begin
  2  for i in 1..10 loop
  3  insert into hwm select * from dba_objects order by i;
  4  commit;
  5  end loop;
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> EXEC SHOW_SPACE('HWM','T','AUTO','Y',NULL,'TRSEN');
Total Blocks............................11264======>hwm=11264
Total Bytes.............................92274688
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................4
Last Used Ext BlockId...................64640
Last Used Block.........................1024
################################
The segment is analyzed
0% -- 25% free space_blocks.............0
0% -- 25% free space_bytes..............0
25% -- 50% free space_blocks............0
25% -- 50% free space_bytes.............0
50% -- 75% free space_blocks............0
50% -- 75% free space_bytes.............0
75% -- 100% free space_blocks...........187
75% -- 100% free space_bytes............1531904
full_blocks.............................10674
full_bytes.............................87441408
Unused Blocks...........................256
Unused Bytes............................2097152
Total Blocks............................10674
Total bytes.............................87441408

PL/SQL procedure successfully completed.

SQL> select count(1) from hwm;
  COUNT(1)
----------
    753000

SQL> delete hwm where rownum<=50000;
50000 rows deleted.

SQL> commit;
Commit complete.

SQL> select count(1) from hwm;
  COUNT(1)
----------
    703000
    

SQL> EXEC SHOW_SPACE('HWM','T','AUTO','Y',NULL,'TRSEN');
Total Blocks............................11264==>HWM没有变化
Total Bytes.............................92274688
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................4
Last Used Ext BlockId...................64640
Last Used Block.........................1024
################################
The segment is analyzed
0% -- 25% free space_blocks.............0
0% -- 25% free space_bytes..............0
25% -- 50% free space_blocks............0
25% -- 50% free space_bytes.............0
50% -- 75% free space_blocks............0
50% -- 75% free space_bytes.............0
75% -- 100% free space_blocks...........894
75% -- 100% free space_bytes............7323648
full_blocks.............................9967
full_bytes.............................81649664
Unused Blocks...........................256
Unused Bytes............................2097152
Total Blocks............................9967
Total bytes.............................81649664

PL/SQL procedure successfully completed.


==>move HWM表,后再看HWM
alter table HWM move;

SQL> EXEC SHOW_SPACE('HWM','T','AUTO','Y',NULL,'TRSEN');
Total Blocks............................10240===>HWM=10240-90+1=10150,高水位降了
Total Bytes.............................83886080
Unused Blocks...........................90
Unused Bytes............................737280
Last Used Ext FileId....................4
Last Used Ext BlockId...................74752
Last Used Block.........................934
################################
The segment is analyzed
0% -- 25% free space_blocks.............0
0% -- 25% free space_bytes..............0
25% -- 50% free space_blocks............0
25% -- 50% free space_bytes.............0
50% -- 75% free space_blocks............0
50% -- 75% free space_bytes.............0
75% -- 100% free space_blocks...........0
75% -- 100% free space_bytes............0
full_blocks.............................10007
full_bytes.............................81977344
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................10007
Total bytes.............................81977344

PL/SQL procedure successfully completed.

那么这里需要问问move到底做了什么动作呢?
我们通常使用这个命令,将一个table segment从一个tablespace移动到另一个tablespace。
Move实际上是在block之间物理的copy数据,那么,我们可以通过这种方式来降低table的HWM。
table里rowid构造,是16进制编码格式
例如:
AAAS6P AAE AAAQFv AAW
分别
数据对象号
文件号
数据块号
行号
查看对象号:
SQL> col object_name for a15;
SQL> col owner for a25;
SQL> SELECT od.object_name, od.owner
  2    FROM dba_objects od
  3   WHERE od.DATA_OBJECT_ID =
  4         (SELECT dbms_rowid.rowid_object('AAAS6PAAEAAAQFvAAW') FROM dual) ;
OBJECT_NAME     OWNER
--------------- -------------------------
HWM             TRSEN

一般情况下,object_id=data_object_id,但是如果做过truncate,move等动作更改块的动作,data_object_id值发生了变化,所以匹配object_id
就定位不到对象,通过data_object_id来处理

查看文件号:
SQL> set linesize 110;
SQL> col file_name for a80;
SQL> col tablespace_name for a15;
SQL> col AUTOEXTENSIBLE for a10
SQL> SELECT ddf.file_name,ddf.tablespace_name,ddf.AUTOEXTENSIBLE
  2    FROM dba_data_files ddf
  3   WHERE ddf.FILE_ID =
  4         (SELECT dbms_rowid.rowid_relative_fno('AAAS6PAAEAAAQFvAAW') FROM dual);
FILE_NAME                                                                        TABLESPACE_NAME AUTOEXTENS
-------------------------------------------------------------------------------- --------------- ----------
/u01/app/oacle/oradata/orcl/users01.dbf                                          USERS           YES

块号及行号
dbms_rowid.rowid_block_number
dbms_rowid.rowid_row_number

我们现在来看看做了move动作后,数据存放的变化
SQL> create table hwm1 (id int,name char(2000));
Table created.

SQL> insert into hwm1 values(1,'a');
1 row created.

SQL> insert into hwm1 values(1,'aa');
1 row created.

SQL> insert into hwm1 values(3,'df');
1 row created.

SQL> insert into hwm1 values(6,'eeee');
1 row created.

SQL> commit;
Commit complete.

SQL> select rowid from hwm1;
ROWID
------------------
AAAS6RAAEAAAAINAAA
AAAS6RAAEAAAAINAAB
AAAS6RAAEAAAAINAAC
AAAS6RAAEAAAAIOAAA
4条数据分别存放在AAAAIN和AAAAIO两个块上

做move动作
alter table HWM1 move;

SQL> select rowid from hwm1;
ROWID
------------------
AAAS6TAAEAAAAILAAA
AAAS6TAAEAAAAILAAB
AAAS6TAAEAAAAILAAC
AAAS6TAAEAAAAIMAAA

4条数据分别存放在AAAAIL一个块上

move对索引的影响
SQL>  create index idx_hwm1 on hwm1 (id);
Index created

SQL> alter table my_objects move;
Table altered

SQL> select index_name,status from user_indexes where index_name='IDX_HWM1';
INDEX_NAME                     STATUS
------------------------------ --------
IDX_HWM1                   UNUSABLE

该table上的inedx的状态为UNUSABLE,这时,我们可以使用alter index IDX_HWM1 rebuild online的命令,对IDX_HWM1进行在线rebuild。


move时对table的锁定
当我们对表HWM进行move操作时,查询v$locked_objects视图可以发现,在表HWM上加了exclusive lock:
SQL>select OBJECT_ID, SESSION_ID,ORACLE_USERNAME,LOCKED_MODE from v$locked_objects;
 OBJECT_ID SESSION_ID ORACLE_USERNAME    LOCKED_MODE
---------- ---------- ------------------ -----------
     77455          11 DLINGER                      6
     
SQL> select object_id from user_objects where object_name = 'HWM';
 OBJECT_ID
----------
     77455

对table进行move操作时,我们只能对它进行select的操作;
反过来说,当我们的一个session对table进行DML操作且没有commit时,在另一个session中是不能对这个table进行move操作的,
否则oracle会返回这样的错误信息:ORA-00054: 资源正忙,要求指定 NOWAIT。

SQL> alter table hwm1 move;
alter table hwm1 move
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

使用alter table move来降低table的HWM时,有一点是需要注意的,这时,当前的tablespace中需要有1倍于table的空闲空间以供使

<think>好的,用户问的是Oracle中如何收缩含有大字段(LOB)的表,也就是使用SHRINK命令处理有大字段的表。首先,我得回忆一下Oracle的SHRINK SPACE操作。记得这个命令是用来回收碎片和释放未使用空间的,但LOB字段的处理可能和普通表不同。 首先,要确认用户是否了解SHRINK的基本使用,比如普通表的收缩步骤。可能需要先介绍常规操作,再讲LOB的特殊情况。因为LOB数据通常存储在单独的段中,可能使用ASSM(自动段空间管理),所以收缩可能需要分开处理。 接下来,考虑用户可能的场景:他们的表有大量LOB数据,导致表空间占用过大,想要通过收缩来释放空间。但LOB字段可能无法像普通数据那样轻易移动,需要特定的方法,比如开启ROW MOVEMENT,或者单独处理LOB段。 然后,需要检查Oracle的版本是否支持LOB段的收缩。可能从10g或11g开始支持?需要确认具体的版本要求。另外,ALTER TABLE SHRINK SPACE CASCADE是否会自动处理LOB段,或者是否需要单独对LOB列进行操作。 还可能需要注意,收缩操作需要表支持行移动,并且可能引起索引的重建,这会导致锁表,影响业务。所以需要提醒用户在维护窗口操作,并做好备份。 另外,要提到DBA_LOBS视图,用来查询LOB字段所在的表空间和段信息,帮助用户确认LOB的存储位置。可能还需要使用DBMS_REDEFINITION在线重定义表,如果直接收缩不可行的话。 用户可能遇到的问题包括:收缩后空间未释放,可能是因为LOB数据未被有效处理,或者HWM(高水位线)未调整。需要解释HWM的概念,以及如何通过MOVE或SHRINK来降低HWM。 最后,整理步骤:先开启行移动,收缩表级,再处理LOB段,可能需要CASCADE参数,或者单独执行ALTER TABLE MODIFY LOB (...) (SHRINK SPACE)。还要提醒空间是否返回给表空间,取决于存储参数和是否启用了自动扩展。 需要确保回答结构清晰,分步骤说明,注意事项和可能的问题,帮助用户全面理解操作过程和潜在风险。</think>在Oracle数据库中,对大字段(LOB)表进行空间收缩需要特殊处理。以下是分步骤说明: ### 1. 收缩前的准备工作 - **开启行移动**(Row Movement): ```sql ALTER TABLE 表名 ENABLE ROW MOVEMENT; ``` 这是SHRINK操作的前提条件,允许Oracle物理重组行位置。 - **确认LOB存储类型**: ```sql SELECT table_name, column_name, tablespace_name, segment_name FROM dba_lobs WHERE table_name = '表名'; ``` 确认LOB字段是否存储在独立段(BASICFILE/SECUREFILE)中。 ### 2. 普通表收缩(非LOB字段) ```sql ALTER TABLE 表名 SHRINK SPACE COMPACT; -- 仅碎片整理 ALTER TABLE 表名 SHRINK SPACE; -- 释放空间并重置HWM ``` ### 3. LOB字段的特殊处理 - **方法1:级联收缩**(CASCADE) ```sql ALTER TABLE 表名 SHRINK SPACE CASCADE; ``` 该命令会级联收缩: - 表段(TABLE) - 索引段(INDEX) - LOB段(LOBSEGMENT) - LOB索引段(LOBINDEX) - **方法2:单独收缩LOB列** ```sql ALTER TABLE 表名 MODIFY LOB(LOB字段名) (SHRINK SPACE); ``` ### 4. 验证收缩效果 ```sql SELECT segment_name, bytes/1024/1024 MB FROM dba_segments WHERE segment_name IN ('表名', 'LOB段名'); ``` ### 注意事项 1. **版本兼容性**: - 需要Oracle 11g及以上版本才支持LOB字段的SHRINK操作 - SECUREFILE类型LOB支持更高效的压缩 2. **锁机制**: - 操作期间会获取表级排他锁(TM) - 建议在维护窗口操作 3. **空间回收限制**: - 无法回收已分配给表空间的未使用空间(需配合数据文件resize操作) - LOB字段的碎片化空间可能无法完全回收 4. **性能影响**: - 会产生大量重做日志(建议开启NOLOGGING模式) - 可能触发全表扫描和行迁移 ### 替代方案 对于超大型LOB表,推荐使用: ```sql ALTER TABLE 表名 MOVE TABLESPACE 新表空间 LOB(字段名) STORE AS (TABLESPACE LOB表空间); ``` 通过物理迁移重组存储结构,更彻底地回收空间。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值