温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

oracle 收缩表、清理碎片,释放空间

发布时间:2020-08-13 14:23:03 来源:ITPUB博客 阅读:991 作者:yangmm 栏目:关系型数据库

可以用来收缩段,消除空间碎片的方法有两种:

1.alter table table_name move

需要注意:

1)move操作会锁表。(如果是很小的表,可以在线做。如果是大表一定要注意,会长时间锁表,只能查询,影响正常业务运行。)
2)move操作会使索引失效,一定要rebuild。(因为move操作会改变一些记录的ROWID,所以MOVE之后索引会变为无效,需要REBUILD。)

2.使用shrink space

alter table table_name shrink space

前提条件

1) 必须启用行记录转移(enable row movement)

2) 仅仅适用于堆表,且位于自动段空间管理的表空间(堆表包括:标准表,分区表,物化视图容器,物化视图日志表)

优点:

提高缓存利用率,提高OLTP的性能

减少磁盘I/O,提高访问速度,节省磁盘空间

段收缩是在线的,索引在段收缩期间维护,不要求额外的磁盘空间

加参数

cascade: 缩小表及其索引,并移动高水位线,释放空间

compact: 仅仅是缩小表和索引,并不移动高水位线,不释放空间

如果在业务繁忙时做压缩,

可以使用alter table shrink space compact来对表格进行碎片整理,而不调整高水位线,之后再次调用alter table table_name shrink space来释放空间。

也可以使用alter table table_name shrink space cascade来同时对索引都进行收缩,这等同于同时执行alter index idxname shrink space。

方法一:move方式收缩表

1)创建一张新表test,并插入数据

SQL>  create table TEST (id int , name char (2000)) tablespace users; 
Table created.
SQL> insert into TEST values (1, 'aa' );
SQL> insert into TEST values (2, 'bb' ); 

SQL> insert into TEST values (3, 'cc' ); 


--查看test表中rowid

SQL> select Dbms_Rowid.rowid_block_number(rowid)  from TEST;

2) 删除表中部分数据,并再次查看表中rowid

SQL> delete from TEST where mod(id,2)=1; 

SQL> select Dbms_Rowid.rowid_block_number(rowid)  from TEST;

3) 对表执行move操作

SQL> alter table TEST move

4)再次查看表中rowid  

SQL> select Dbms_Rowid.rowid_block_number(rowid)  from TEST;

小结: 1

move操作后,数据的rowid发生了改变,我们知道,index是通过rowid来获取数据行的,所以table上的index是必须要rebuild的。

5) 查看表中索引情况,此时索引为失效的

SQL> select index_name,status from user_indexes where index_name='TEST_INDEX';

INDEX_NAME                        STATUS

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

TEST_INDEX                          UNUSABLE

6)在线重建索引

SQL> alter index TEST_MOVE_INDEX rebuild online;


小结:2

move操作后,表中索引会失效

--查看锁情况

SQL> SELECT b.session_id AS sid,  

          NVL(b.oracle_username, '(oracle)') AS username,  

          a.owner AS object_owner,  

          a.object_name,  

           Decode(b.locked_mode, 0, 'None',  

                                1, 'Null (NULL)',  

                               2, 'Row-S (SS)',  

                                3, 'Row-X (SX)',  

                                4, 'Share (S)',  

                                5, 'S/Row-X (SSX)',  

                               6, 'Exclusive (X)',  

                               b.locked_mode) locked_mode,  

           b.os_user_name  

    FROM   dba_objects a,  

         v$locked_object b  

    WHERE  a.object_id = b.object_id;

      SID          USERNAME          OBJECT_OWNER       OBJECT_NAME        LOCKED_MODE        OS_USER_NAME

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

        33          YMM                          YMM                    TEST                         Exclusive (X)                  oracle

小结:3

--Exclusive (X) 是6号锁,独占锁。  

--这就意味着,table在进行move操作时,我们只能对它进行select的操作。

也就是说当我们的一个session对table进行DML操作且没有commit时,在另一个session中是不能对这个table进行move操作的,

否则oracle会返回这样的错误信息:ORA-00054 。

SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST';

SEGMENT_NAME          EXTENTS      BLOCKS      INIT

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

TEST                                   3               1280         10

--TEST表初始分配了10M的空间,1280个BLOCKS。

SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';

TABLE_NAME               BLOCKS   EMPTY_BLOCKS

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

TEST

--USER_TABLES视图显示有0个使用的BLOCKS,1280个空闲BLOCKS。

--向表中插入数据

SQL> insert into TEST select * from information;

SQL> analyze table TEST compute statistics;

SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST';

SEGMENT_NAME          EXTENTS  BLOCKS       INIT

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

TEST                                 3              1280         10

SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';

TABLE_NAME                         BLOCKS EMPTY_BLOCKS

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

TEST                                        1006          274

--插入数据后,分配的空间仍不变,因为10M还没使用完。显示使用了1006个BLOCKS,空闲274个BLOCKS。这时候的1006 BLOCKS即是高水位线。

SQL> commit;

SQL> select count(*) from test;

  COUNT(*)

----------

    122513

SQL> delete from test  where rownum<=50000;

SQL> analyze table test compute statistics;

SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST';

SEGMENT_NAME                EXTENTS     BLOCKS       INIT

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

TEST                                       3               1280         10

SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';

TABLE_NAME                         BLOCKS EMPTY_BLOCKS

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

TEST                                         1006          274

SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks from test;

USED_BLOCKS

-----------

        573

--这边可以看到,删掉部分数据后,仍然显示使用了1006个BLOCKS,高水位没变。但查询真正使用的BLOCK数只有573个。所以DELETE操作是不会改变HWM的。

SQL> alter table TEST move;   

SQL> analyze table TEST compute statistics;

SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST';

SEGMENT_NAME                 EXTENTS     BLOCKS       INIT

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

TEST                                         3              1280         10

SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';

TABLE_NAME           BLOCKS EMPTY_BLOCKS

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

TEST                           592          688

小结:4

--MOVE之后,HWM降低了,空闲块也上去了。

--但是分配的空间并没有改变,仍然是1280个BLOCKS。

方法二:shrink space方式收缩表

SQL> delete from test  where rownum<=50000;

--首先设置允许行迁移

SQL> alter table TEST enable row movement;

SQL> alter table TEST  shrink space;

SQL> analyze table TEST compute statistics;     -->使用analyze更新统计信息后EMPTY_BLOCKS得到数据  

SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST';

SEGMENT_NAME             EXTENTS         BLOCKS       INIT

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

TEST                                     1                   600            10

SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';

TABLE_NAME                         BLOCKS    EMPTY_BLOCKS

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

TEST                                         592            8

--SHRINK SPACE真正做到了对段的压缩,包括初始分配的也压了,所以它是回收高水位线操作。

验证cascade与compact的差异   

--删除一些数据

SQL> delete from test where rownum<8000;                                                     

                                                                                                                   

SQL> alter table test shrink space compact;  -->使用compact方式收缩表段                                                                                                                                                                                                                    

SQL> exec show_space('TEST','SCOTT');                                                                           

Unformatted Blocks .....................               0                                                             

FS1 Blocks (0-25) ......................               1                                                             

FS2 Blocks (25-50) .....................               2                                                             

FS3 Blocks (50-75) .....................               0                                                             

FS4 Blocks (75-100).....................             103                                                             

Full Blocks ............................          14,214 --仅有的变化为14318-14214=104块,即完全填满的数据块减少了104块

Total Blocks............................          14,488 --数据的总块数及总大小并没有减少,即未移动高水位线          

Total Bytes.............................     118,685,696                                                             

Total MBytes............................             113                                                             

Unused Blocks...........................               5                                                             

Unused Bytes............................          40,960                                                             

Last Used Ext FileId....................               4                                                             

Last Used Ext BlockId...................          16,521                                                             

Last Used Block.........................             147                                                             

                                                                                                                     

PL/SQL procedure successfully completed.                                                                             

                                                                                                                     

SQL> alter table test shrink space cascade;  -->使用cascade方式收缩                                                                                                                                              

                                                                                                                     

SQL> exec show_space('TEST','SCOTT');                                                                           

Unformatted Blocks .....................               0                                                             

FS1 Blocks (0-25) ......................               1                                                             

FS2 Blocks (25-50) .....................               2                                                             

FS3 Blocks (50-75) .....................               0                                                             

FS4 Blocks (75-100).....................               0                                                             

Full Blocks ............................          14,214                                                             

Total Blocks............................          14,384   -->总块数及总大小均已减少                                 

Total Bytes.............................     117,833,728                                                             

Total MBytes............................             112                                                             

Unused Blocks...........................               4                                                             

Unused Bytes............................          32,768                                                             

Last Used Ext FileId....................               4                                                             

Last Used Ext BlockId...................          16,521                                                             

Last Used Block.........................              44                                                             

                                                                                                                     

PL/SQL procedure successfully completed.                                                                             

                                                                                                                     

-->收缩之后索引依然有效                                                                                              

SQL> select OWNER,INDEX_NAME,STATUS from dba_indexes where TABLE_NAME='TEST';                                   

                                                                                                                     

OWNER              INDEX_NAME         STATUS                                                 

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

SCOTT                    idx_test                 VALID     

小结:

compact:仅仅是缩小表和索引,并不移动高水位线,不释放空间

cascade:缩小表及其索引,并移动高水位线,释放空间

语法总结:

ALTER TABLE <table_name> ENABLE ROW MOVEMENT   -->前提条件                                       

                                                                                                 

ALTER TABLE <table_name> SHRINK SPACE [ <NULL> | COMPACT | CASCADE ];                            

                                                                                                 

ALTER TABLE <table_name> SHRINK SPACE COMPCAT;  -->缩小表和索引,不移动高水位线,不释放空间      

                                                                                                 

ALTER TABLE <table_name> SHRINK SPACE;     -->收缩表,降低高水位线;                              

                                                                                                 

ALTER TABLE <table_name> SHRINK SPACE CASCADE; -->收缩表,降低高水位线,并且相关索引也要收缩一下 

                                                                                                 

ALTER TABLE <table_name> MODIFY LOB (lob_column) (SHRINK SPACE);  -->收缩LOB段                   

                                                                                                 

ALTER INDEX IDXNAME SHRINK SPACE; 


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI