ORACLE查詢表數據占用存儲空間大小(清理表碎片)


查詢”帳戶/庫”數據占用存儲空間大小
select sum(bytes)/1024/1024 as “size(M)” from dba_segments where owner=’帳戶名/庫名’

查詢單表數據占用存儲空間大小
select sum(bytes)/(1024*1024) as “size(M)” from user_segments
where segment_name=upper(‘表名’);

在表空間中,查詢占用存儲空間最大的表
SELECT * FROM (SELECT SEGMENT_NAME, SUM(BYTES) / 1024 / 1024 MB FROM DBA_SEGMENTS WHERE TABLESPACE_NAME = upper(‘表空間名稱’) GROUP BY SEGMENT_NAME ORDER BY 2 DESC) WHERE ROWNUM < 10;

在”帳戶/庫”中,查詢占用存儲空間最大的表
SELECT * FROM (SELECT SEGMENT_NAME, SUM(BYTES) / 1024 / 1024 MB FROM DBA_SEGMENTS WHERE owner=upper(‘帳戶名/庫名’) GROUP BY SEGMENT_NAME ORDER BY 2 DESC) WHERE ROWNUM < 10;

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

為什么我的表delete數據之后再插入同樣的數據,表空間占用會越來越大?

我的操作首先是
DELETE TABLE A WHERE A.UPDATE>=一個固定的日期
然后commit
之后INSERT INTO TABLE A 剛才刪除的數據
前后表數據數量是一樣的,但是莫名其妙的表空間卻越占越大
沒有lob字段。

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

樓主研究一下 pctfree 和  pctused 這兩個參數,跟這個會有關系的;

這時,你可以 move 一下表,大小就應該和原來的一樣了。

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

清理存儲碎片

alter table 表名稱 move

 

alter table move 操作來清理存儲碎片,其實是讀取t,然后在t表所在的表空間重建表t.等moce

操作完成之后刪除原來的表。所以需要額外的存儲空間開銷,要求當前表空間的大小至少為

表的兩倍

 

注意:

1.再用alter table table_name move時,表相關的索引會失效,所以之后還要執行 alter index index_name rebuild online; 最后重新編譯數據庫所有失效的對象

2. 在用alter table table_name shrink space cascade時,他相當於alter table table_name move和alter index index_name rebuild online. 所以只要編譯數據庫失效的對象就可以

 

--查詢碎片情況

exec show_space('T');

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

alter table move跟shrink space的區別

今天主要從兩點說他們的區別:

1. 碎片的整理

2.空間的收縮

 

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production

TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SQL>

 

創建測試表
SQL> create table test3 as
  2     select rownum id,
  3     dbms_random.string('a', round(dbms_random.value(0,10))) col1,
  4     trunc(sysdate) - dbms_random.value(1, 365*2) col2
  5     from dual connect by rownum<=10000;

Table created

 

SQL> select count(1) from test3;

  COUNT(1)
----------
     10000


查看表test3的blocks使用情況:

 

SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
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
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................32
Total bytes.............................262144

 

PL/SQL procedure successfully completed

制造碎片

SQL> DELETE FROM TEST3 WHERE MOD(ID,3)=1;

3334 rows deleted

 

SQL> commit;

Commit complete

 

發現有碎片了

 

SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............31
25% -- 50% free space bytes.............253952
50% -- 75% free space blocks............1
50% -- 75% free space bytes.............8192
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................0
Total bytes.............................0

 

PL/SQL procedure successfully completed

SQL>

消除碎片

SQL> alter table test3 move;

Table altered

 

查看碎片消除的效果


SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................31
Last Used Ext BlockId...................485065
Last Used Block.........................2
 *************************************************
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
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................22
Total bytes.............................180224

 

PL/SQL procedure successfully completed

SQL>

 

從以上看,碎片整理的效果很好!!!

下面在測試用shrink整理碎片

重建測試環境


SQL> drop table test3;

Table dropped

 

SQL>
SQL> create table test3 as
  2     select rownum id,
  3     dbms_random.string('a', round(dbms_random.value(0,10))) col1,
  4     trunc(sysdate) - dbms_random.value(1, 365*2) col2
  5     from dual connect by rownum<=10000;

Table created

 

查看test3的blocks的使用


SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
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
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................32
Total bytes.............................262144

 

PL/SQL procedure successfully completed

 

制造碎片


SQL> delete from test3 where mod(id,3)=1;

3334 rows deleted

 

SQL> commit;

Commit complete

 

查看碎片情況
SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............31
25% -- 50% free space bytes.............253952
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................1
Total bytes.............................8192

 

PL/SQL procedure successfully completed

 

用oracle10g新功能整理碎片


SQL> alter table test3 shrink space compact cascade;

alter table test3 shrink space compact cascade

ORA-10636: ROW MOVEMENT is not enabled

 

SQL> alter table test3 enable row movement;

Table altered

 

SQL> alter table test3 shrink space compact cascade;

Table altered

 

再次查看碎片的情況,發現還有一些碎片,整理碎片效果不好


SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............1
0% -- 25% free space bytes..............8192
25% -- 50% free space blocks............2
25% -- 50% free space bytes.............16384
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........12
75% -- 100% free space bytes............98304
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................17
Total bytes.............................139264

 

PL/SQL procedure successfully completed

 

上面是沒降低HWM,如果載降低HWM,看看效果


SQL> alter table test3 shrink space cascade;

Table altered

SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................24
Total Bytes.............................196608
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................31
Last Used Ext BlockId...................481897
Last Used Block.........................8
 *************************************************
0% -- 25% free space blocks.............1
0% -- 25% free space bytes..............8192
25% -- 50% free space blocks............2
25% -- 50% free space bytes.............16384
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................17
Total bytes.............................139264

 

PL/SQL procedure successfully completed

 

看來用shrink space整理碎片不徹底,再來看看move的方式

 

SQL> alter table test3 move;

Table altered

SQL> exec show_space_t('TEST3','auto','table','Y');

Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................31
Last Used Ext BlockId...................485081
Last Used Block.........................2
 *************************************************
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
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................22
Total bytes.............................180224

PL/SQL procedure successfully completed

效果很明顯,整理的很徹底

 

測試結論:

雖然alter table move和shrink space,都是通過物理調整rowid來整理碎片的,但shrink space整理的不徹底,他好像不是重組,而是盡可能的合並,隨意會殘留一些block無法整理

 

注意:

1.再用alter table table_name move時,表相關的索引會失效,所以之后還要執行 alter index index_name rebuild online; 最后重新編譯數據庫所有失效的對象

2. 在用alter table table_name shrink space cascade時,他相當於alter table table_name move和alter index index_name rebuild online. 所以只要編譯數據庫失效的對象就可以

 

alter table move和shrink space除了碎片整理的效果有時不一樣外,還有什么其他的不同呢

1. Move會移動高水位,但不會釋放申請的空間,是在高水位以下(below HWM)的操作。
2. shrink space 同樣會移動高水位,但也會釋放申請的空間,是在高水位上下(below and above HWM)都有的操作。

 

下面通過實驗來驗證


SQL> drop table test3;

Table dropped

 

SQL>
SQL> create table test3 as
  2     select rownum id,
  3     dbms_random.string('a', round(dbms_random.value(0,10))) col1,
  4     trunc(sysdate) - dbms_random.value(1, 365*2) col2
  5     from dual connect by rownum<=10000;

Table created

 

SQL> analyze table test3 compute statistics;

Table analyzed

                                                                         

SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');

SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               5         40

 

SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              37            3

SQL>


從以上查詢可以看出共分了5個extents,使用了37個blocks,這37也就是test3的HWM

 

SQL> delete from test3 where rownum<=5000;

5000 rows deleted

 

SQL> commit;

Commit complete

 

SQL> analyze table test3 compute statistics;

Table analyzed

 

SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');

SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               5         40

 

SQL> col table_name for a10;
SQL>  select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              37            3

 

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

USED_BLOCKS
-----------
         17


我們從查詢中可以發現test3的HWM沒有變換還是37blocks,tests總共空間為40blocks。經過刪除后test3實際用的塊是17個

下面我們用move降低下HWM

 

SQL> alter table test3 move;

Table altered

 

SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');

SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               3         24

 

SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              37            3

 

user_tables里的數據沒有變化,哦,原來是忘記analyze了,從這里也可以看出user_segments是oracle自動維護的。

 

SQL> analyze table test3 compute statistics;

Table analyzed

 

SQL>  select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');

SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               3         24

 

SQL> select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              20            4

SQL>


現在再來看hwm變為20了,已經降下來了啊,空間也收縮了,從40blocks降到24blocks(注意收縮到initial指定值)。
但shrink space就收縮到存儲數據的最小值,下面測試說明

創建測試表:


SQL>   create table test5 (id number) storage (initial 1m next 1m);

Table created

 

初始化數據


SQL>
SQL>   begin
  2     for i in 1..100000 loop
  3     insert into test5 values(i);
  4    end loop;
  5    end;
  6  /

PL/SQL procedure successfully completed

 

SQL> analyze table test5 compute statistics;

Table analyzed

 

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

SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              17        256          1

 

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

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5             180           76

 

可以從查詢數據看出,test5初始化1m即128個blocks,但數據比較多,所以又按next參數要求擴展了1m空間,擴展了17個extents。
這里的test5總空間大小為256個blocks,使用空間為180blocks,HWM也是180blocks


SQL> delete from test5 where rownum<=50000;

50000 rows deleted

 

SQL> analyze table test5 compute statistics;

Table analyzed

 

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

SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              17        256          1

 

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

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5             180           76

 

整理碎片,降低HWM


SQL>  alter table test5 move;

Table altered


SQL> analyze table test5 compute statistics;

Table analyzed

 

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

SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              16        128          1

 

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

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5              85           43

 

從上面的查詢數據可以看出HWM已經從180降低到85,test5總大小從256blocks收縮到128個blocks(initial指定大小)。

下面看看用shrink space收縮空間的情況

SQL> alter table test5 enable row movement;

Table altered


SQL> alter table test5 shrink space;

Table altered

 

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

SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              11         88          1

 

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

TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5              85           43

SQL>

從上面的數據可以看到test5進一步從128個blocks降低到88個blocks

結論:

shrink space收縮到數據存儲的最小值,alter table move(不帶參數)收縮到initial指定值,也可以用alter table test5 move storage(initial 500k)指定收縮的大小,這樣可以達到shrink space效果

經過以上測試,得出的兩個結論,到底用哪一個命令來整理碎片,消除行遷移呢?這就要根據實際業務需要,如果你只是收縮空間,數據增長很慢,那用shrink可以但是如果數據增長很快的話,用move就比較合適,避免再重新分配空間啊

備注:
在10g之后,整理碎片消除行遷移的新增功能shrink space

alter table <table_name> shrink space [ <null> | compact | cascade ];

compact:這個參數當系統的負載比較大時可以用,不降低HWM。如果系統負載較低時,直接用alter table table_name shrink space就一步到位了

cascade:這個參數是在shrink table的時候自動級聯索引,相當於rebulid index。

普通表:

shrink必須開啟行遷移功能。
alter table table_name enable row movement ;

保持HWM,相當於把塊中數據打結實了
alter table table_name shrink space compact;

回縮表與降低HWM
alter table table_name shrink space;

回縮表與相關索引,降低HWM
alter table table_name shrink space cascade;

回縮索引與降低HWM
alter index index_name shrink space

雖然在10g中可以用shrink ,但也有些限制:

1). 對cluster,cluster table,或具有Long,lob類型列的對象 不起作用。
2). 不支持具有function-based indexes 或 bitmap join indexes的表
3). 不支持mapping 表或index-organized表。
4). 不支持compressed 表

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM