【原創】Oracle 資料結構知多少(一)

leonarding發表於2013-04-08

更多精彩內容請光臨

Oracle 資料結構知多少(一)》

概念篇

這裡呢我只是把Oracle邏輯結構和物理結構所涉及到的segment  extent  block塊的概念和相互管理簡要的說明一下。

Segment段:Oracle內部常叫“段物件”,凡是分配儲存空間的物件就叫段物件。既可以自動段空間管理ASSM,又可以手動段空間管理MSSM。段屬性依賴於塊屬性。

Extent區:多個區組成一個段,區是Oracle最小的分配單元,區與區不一定是連續的,區可以分佈在不同的資料檔案上。

Block塊:一片連續的塊組成一個區,是Oracle最小的IO單元,最小的操作單元,RMAN備份/恢復最小單元,資料庫塊是作業系統塊的整數倍。

資料I/O:由磁碟與記憶體之間的通道決定的,而不是由資料怎麼分割決定的。分割只是善於管理,I/O方面影響不大。(例如 放在一個表空間和放在多個表空間)

一方面I/O通道導致效能下降

一方面latch爭用導致效能下降


資料庫版本

LEO1@LEO1> select * from v$version;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

PL/SQL Release 11.2.0.1.0 - Production

CORE    11.2.0.1.0      Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production

實驗篇

1.檢視一個表空間,有多少個extents,多少blocks,多少空餘空間。

檢視錶空間空間使用情況,我想這是100%DBA每天都要做的工作,現在我把自己常用的表空間查詢語句測試一下。

LEO1@LEO1> select df.tablespace_name "表空間名",totalspace "總空間M",freespace "剩餘空間M",round((1-freespace/totalspace)*100,2) "使用率%"

from

(select tablespace_name,round(sum(bytes)/1024/1024) totalspace from dba_data_files group by tablespace_name) df,

(select tablespace_name,round(sum(bytes)/1024/1024) freespace from dba_free_space group by tablespace_name) fs

where df.tablespace_name=fs.tablespace_name order by df.tablespace_name ;   

表空間名                 總空間M     剩餘空間M     使用率%

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

LEO1                     400           248           38       業務表空間

SYSAUX                   610           38            93.77

SYSTEM                   710           18            97.46

UNDOTBS1                165           134           18.79

UNDOTBS2                100           0             100

USERS                    5             4             20

檢視一個表空間,有多少個extents,多少blocks呢?

LEO1@LEO1> select tablespace_name,file_id,extent_id,block_id,blocks from dba_extents where tablespace_name='LEO1' order by extent_id;

TABLESPACE_NAME                   FILE_ID  EXTENT_ID   BLOCK_ID     BLOCKS

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

LEO1                                    5         22      39040        128

LEO1                                    5         22      40192        128

LEO1                                    5         22      41344        128

LEO1                                    5         22      42752        128

LEO1                                    5         22       8576        128

LEO1                                    5         22       9216        128

LEO1                                    5         22       3712        128

LEO1                                    5         23       1152        128

LEO1                                    5         23      35456        128

LEO1                                    5         23      36864        128

LEO1                                    5         23      38016        128

LEO1                                    5         23      39168        128

LEO1                                    5         23      40320        128

LEO1                                    5         23      41472        128

LEO1                                    5         23      42880        128

LEO1                                    5         23       8704        128

LEO1                                    5         23       9344        128

LEO1                                    5         23       3840        128

711 rows selected.

這裡一共711行,沒有都列印出來,我們只把相關幾列的含義給大家說明

FILE_IDLEO1表空間對應的資料檔案號

EXTENT_ID:這個資料檔案裡包含了多少個區

BLOCK_ID:每個區起始的資料塊號

BLOCKS:每個區包含的資料塊數

把上面的引數彙總一下就可以看出一個表空間包含有多少個extents多少blocks了。

2.示例演示透過rowid得到資料塊的相關資訊(所在物件,檔案,資料塊)

rowOracle處理資料的最小單位,至少會掃描一行,也是lock的最小單位,不同使用者可以修改不同的行,因為是行級鎖由ITL事物槽控制。

rowid:我想大家對這個東東應該都不會陌生,說白了就是行的物理磁碟地址,由十六進位制表示,由行頭和行體組成。

行頭:記錄行的屬性資訊方便管理。

行體:記錄欄位的值,即資料。

下面我們來看看rowid在資料庫中是如何表示的

LEO1@LEO1> drop table leo1 purge;                                          清空環境

Table dropped.

LEO1@LEO1> create table leo1 as select * from dba_objects where object_id in (1,2,3);   建立表

Table created.

LEO1@LEO1> select rowid,object_id,object_name from leo1;         表中記錄及對應的rowid

ROWID                  OBJECT_ID     OBJECT_NAME

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

AAASKGAAFAAAAWzAAA    3            I_OBJ#

AAASKGAAFAAAAWzAAB    2            C_OBJ#

我們數了一下rowid18位字元組成,每組字元代表不同的含義,18位最大定址空間“32G

AAASKG:物件id

AAF:檔案id

AAAAWz:塊id

AAA:行id

這四部分唯一標識了一行的實體地址,基於rowid的資料查詢是最快的,比index還要快

下面我們使用DBMS_ROWID包來得到資料塊的相關資訊

LEO1@LEO1> select rowid,dbms_rowid.rowid_object(rowid) object_id,

dbms_rowid.rowid_relative_fno(rowid) file_id,

dbms_rowid.rowid_block_number(rowid) block_id,

dbms_rowid.rowid_row_number(rowid) row_id

from leo1;  2    3    4    5  

ROWID                    OBJECT_ID    FILE_ID   BLOCK_ID     ROW_ID

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

AAASKGAAFAAAAWzAAA      74374        5        1459         0

AAASKGAAFAAAAWzAAB      74374        5        1459         1

LEO1@LEO1> select object_name from dba_objects where object_id=74374;

OBJECT_NAME

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

LEO1

上面兩行記錄的物件名即為Leo1,所屬檔案號是5(同一個檔案),所屬塊號是1459(同一個塊),所屬行號0(第一行)1(第二行)以此類推。

小結:如果我們想要了解資料行的物理結構,那麼可以透過DBMS_ROWID包來得到資料行的相關資訊。


3.示例說明consistent read,current read,logical read,physical read的概念及關係

Logical read:所謂邏輯讀,就是從記憶體中讀取資料塊,包含current read consistent read

current read:屬於Oracle版本讀取方式的一種機制,就是說當進行DML操作時,我們需要獲取資料塊最新的狀態,只對最新狀態進行操作,操作期間鎖定資料行。

consistent read:當進行select查詢時,我們需要獲取查詢那一刻資料塊狀態,不管查詢了多長時間,我們只要查詢那一瞬間的結果,如果查詢期間資料塊被修改,那麼我們就去undo segment讀取舊映像來呈現。

公式:logical read=db block gets(current read) + consistent gets(consistent read)

Physical read:所謂物理讀,就是從磁碟中讀取資料塊

如果想了解更多的current read consistent read的資訊請參考如下連結

《Oracle undo我們需要掌握什麼》 第五小題“示例分別說明什麼是consistent readcurrent read?

http://space.itpub.net/26686207/viewspace-757488

LEO1@LEO1> drop table leo2 purge;                        清空環境

Table dropped.

LEO1@LEO1> create table leo2 as select * from dba_objects;     建立leo2

Table created.

LEO1@LEO1> set autotrace traceonly

LEO1@LEO1> select count(*) from leo2;                      檢視一下SQL語句統計資訊

Statistics

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

         28  recursive calls

          0  db block gets

       1100  consistent gets      邏輯讀中一致性讀,發生了1100次(從記憶體中讀取資料塊)

       1025  physical reads       物理讀發生了1025次(從磁碟中讀取資料塊)

          0  redo size

        528  bytes sent via SQL*Net to client

        524  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

邏輯讀與物理讀關係:邏輯讀觸發物理讀的發生,因為oracle預設資料塊在記憶體中,如果發現塊不在記憶體裡,就會觸發物理讀從磁碟上讀取資料塊到記憶體,在進行下面的邏輯讀。

有物理讀必有邏輯讀,有邏輯讀不一定有物理讀,看看下面的樣子

LEO1@LEO1> select count(*) from leo2;

Statistics

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

          0  recursive calls

          0  db block gets

       1030  consistent gets           只有邏輯讀1030

          0  physical reads            沒有物理讀

          0  redo size

        528  bytes sent via SQL*Net to client

        524  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

原因:資料塊現在已經全部快取到記憶體中了,我們從記憶體中讀取塊即可,不用再從磁碟中讀取塊了,自然就沒有物理讀。

4.設計一個例子,演示PCTUSEDPCTFREE對資料操作的影響

PCTUSEDPCTFREE是資料塊的儲存屬性,單位都是%

PCTFREE:表示什麼時候不可以再往塊中插入資料,但是更新資料和刪除資料是可以的。例如 我們設定為20%,當資料塊空閒空間剩餘20%時候,這個資料塊就從空閒列表(free list)中移出,移出後我們就不能再往資料塊裡面插入資料了。對於資料塊中已有資料的更新可以使用資料塊中的保留空間,只有當資料塊的佔用空間比例(PCTUSED)低於40%時才能向其插入新資料。

PCTUSED:表示什麼時候可以繼續往塊中插入資料,例如 我們設定40%,只有當資料塊佔用容量低於40%時才允許再次插入新資料,此時資料塊會插入空閒列表(free list),資料塊就能夠繼續接受新記錄,過程如此往復迴圈。

PCTUSEDPCTFREE二者沒有任何關係,各做各的

場景:應用在OLTP系統上多,因為OLTP是一種多事務短時間片操作頻繁的系統,設定資料塊可以存放多少記錄的容量有利於提高系統IO效能

Oracle 10g 11g PCTFREE預設值是10%,設定較高意味著資料塊沒有被利用多少就從freelist中移出,不利於資料塊的充分使用(適合頻繁更新的操作)。設定較低意味著更新時候會出現行遷移,從而也會影響Oracle的效能(適合頻繁插入的操作)。

PCTUSED預設值是40%,設定較高意味著相對較滿的資料塊可有效迴圈使用空閒空間頻繁插入,會導致IO資源的消耗較大,設定較低意味著當一個資料塊快空的時候才被放入freelist,資料塊一次可以插入很多資料,減少IO資源的消耗。

一般這兩個值的總和不要大過90,否則會使Oracle將更多的時間花費在處理空間利用率上

實驗

LEO1@LEO1> drop table leo4 purge;                         清空環境

Table dropped.

LEO1@LEO1> create table leo4 as select * from dba_objects;      建立一個新的leo4

Table created.

LEO1@LEO1> col table_name for a10

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used from user_tables where table_name='LEO4';

TABLE_NAME    TABLESPACE_NAME     PCT_FREE    PCT_USED

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

LEO4           LEO1                 10

LEO4表所在的表空間是ASSM段管理方式,在使用點陣圖管理段空間的情況不可定義PCTUSED,只有使用MSSM段管理方式,在字典管理模式下才可呼叫free list,這2個引數可設定生效。

LEO1@LEO1> select segment_name,blocks,freelists from dba_segments where segment_name='LEO4';

SEGMENT_NAME     BLOCKS  FREELISTS

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

LEO4               1152

我們建立的leo4表,佔用1152個資料塊,freelistfreelistgroupASSM表空間中根本不存在,僅在MSSM表空間使用這個技術

詳細出處參考:

LEO1@LEO1> alter table leo4 pctfree 50;        修改pctfree=50

Table altered.

LEO1@LEO1> alter table leo4 pctused 40;        修改pctused=40

Table altered.

LEO1@LEO1> alter table leo4 move tablespace new_leo1;  把表leo4遷移到new_leo1表空間

Table altered.

new_leo1這個表空間是我之前已經建立好的一個ASSM表空間

語法:create tablespace new_leo1 datafile '/u01/app/oracle/oradata/LEO1/new_leo1.dbf' size 20m autoextend off;

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used from user_tables where table_name='LEO4';

TABLE_NAME    TABLESPACE_NAME     PCT_FREE    PCT_USED

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

LEO4           NEW_LEO1            50

從這裡可以看到leo4表已經從leo1表空間遷移到new_leo1表空間了,pct_free也修改為50,而pct_usedASSM模型下依然不會生效的,freelist也不會生效。

LEO1@LEO1> select segment_name,blocks,freelists from dba_segments where segment_name='LEO4';

SEGMENT_NAME     BLOCKS  FREELISTS

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

LEO4               1920

從這裡可以看到leo4表佔用的塊數從1152上升到1920,這就是因為我們修改了pctfree值得結果,原來預設值為10%的時候,我們可以有90%空間插入資料,現在修改成了50%,我們就只能有50%空間插入資料,存放資料的空間比從90%下降到50%,當資料總量不變的情況下,就只有增加資料塊的個數來解決了。

下面我們演示PCTUSED引數的影響

MSSM:由你設定freelistsfreelistgroupspctusedpctfreeinitrans等引數來控制如何分配、使用段中的空間

ASSM:你只需控制一個引數pctfree,其他引數即使建了也將被忽略

LEO1@LEO1> create tablespace mssm_leo1 datafile '/u01/app/oracle/oradata/LEO1/mssm_leo1.dbf' size 50m autoextend off segment space management manual;

Tablespace created.

LEO1@LEO1> select tablespace_name,segment_space_management from user_tablespaces where tablespace_name in ('LEO1','NEW_LEO1','MSSM_LEO1');

TABLESPACE_NAME                SEGMEN

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

LEO1                           AUTO

NEW_LEO1                      AUTO

MSSM_LEO1                     MANUAL

我們建立一個手動段空間管理MSSM的表空間,在上面建立個新表leo5

LEO1@LEO1> drop table leo5 purge;                清理環境

Table dropped.

LEO1@LEO1> create table leo5 tablespace mssm_leo1 as select * from dba_objects;

Table created. 建立表並指定MSSM表空間儲存

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,freelists,freelist_groups from user_tables where table_name='LEO5';

TABLE_NAME TABLESPACE_N    PCT_FREE   PCT_USED  FREELISTS FREELIST_GROUPS

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

LEO5        MSSM_LEO1     10         40         1        1

此時我們就可以使用上述引數來控制如何分配和使用段中空間了

LEO1@LEO1> select segment_name,blocks,freelists,freelist_groups from dba_segments where segment_name='LEO5';

SEGMENT_NAME     BLOCKS  FREELISTS FREELIST_GROUPS

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

LEO5               1152          1               1

LEO1@LEO1> alter table leo5 pctfree 20;

Table altered.

LEO1@LEO1> alter table leo5 pctused 50;

Table altered.

LEO1@LEO1> select segment_name,blocks,freelists,freelist_groups from dba_segments where segment_name='LEO5';

SEGMENT_NAME     BLOCKS  FREELISTS FREELIST_GROUPS

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

LEO5               1152          1               1

pctused的變化並不會影響第一次載入的資料,因為原始資料塊一開始都是空的,不管如何設定pctused資料都可以順利載入進來,只對後面的載入會有影響。

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,freelists,freelist_groups from user_tables where table_name='LEO5';

TABLE_NAME TABLESPACE_N    PCT_FREE   PCT_USED  FREELISTS FREELIST_GROUPS

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

LEO5        MSSM_LEO1     20         50         1        1

我們修改一下pctfreepctused,可以看到在MSSM段空間管理模式下都是生效的。

LEO1@LEO1> drop table leo6 purge;     清理環境

Table dropped.

LEO1@LEO1> drop table leo7 purge;

Table dropped.

LEO1@LEO1> create table leo6 tablespace mssm_leo1 as select * from dba_objects; 建立leo6

Table created.

LEO1@LEO1> create table leo7 tablespace mssm_leo1 as select * from dba_objects; 建立leo7

Table created.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO6');

PL/SQL procedure successfully completed.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO7');

PL/SQL procedure successfully completed.

進行統計分析收集表儲存資訊

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name='LEO6';

TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS

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

LEO6         MSSM_LEO1     10         40           1024     1       1

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name='LEO7';

TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS

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

LEO7         MSSM_LEO1     10         40           1024     1       1

我們在初始化表時,PCT_FREE=10  PCT_USED=40   BLOCKS=1024,下面我們只修改PCT_USED

LEO1@LEO1> alter table leo6 pctused 30;

Table altered.

LEO1@LEO1> alter table leo7 pctused 60;

Table altered.

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name in ('LEO6','LEO7');

TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS

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

LEO6         MSSM_LEO1     10         30           1024     1       1

LEO7         MSSM_LEO1     10         60           1024     1       1

已經修改完成,但沒有影響資料塊分配數量,這是正常的,既然PCT_USED是表示何時該插入的閥值,那麼我們可以delete where where object_type in ('TABLE','INDEX','VIEW','SEQUENCE');一些記錄,降低到閥值的允許範圍內,在插入一些記錄,設定較高意味著相對較滿的資料塊可有效迴圈使用空閒空間頻繁插入,此時佔用的資料塊應該較少,反之較多。

LEO1@LEO1> delete from leo6 where object_type in ('TABLE','INDEX','VIEW','SEQUENCE');

11870 rows deleted.

LEO1@LEO1> delete from leo7 where object_type in ('TABLE','INDEX','VIEW','SEQUENCE');

11870 rows deleted.                              刪除11870

LEO1@LEO1> insert into leo6 select * from leo5;

71969 rows created.

LEO1@LEO1> insert into leo7 select * from leo5;

71969 rows created.                              插入71969

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO6');

PL/SQL procedure successfully completed.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO7');

PL/SQL procedure successfully completed.

LEO1@LEO1> select table_name,tablespace_name,pct_free,pct_used,blocks,freelists,freelist_groups from user_tables where table_name in ('LEO6','LEO7');

TABLE_NAME  TABLESPACE_N   PCT_FREE   PCT_USED     BLOCKS  FREELISTS FREELIST_GROUPS

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

LEO6         MSSM_LEO1     10         30           1959    1        1

LEO7         MSSM_LEO1     10         60           1901    1        1

小結:leo7佔用資料塊比leo6少,是因為當後續載入資料時,Oracle會根據PCT_USED引數動態調節資料塊何時可以繼續插入資料,當刪除後閥值降到了60%以下就可以往leo7表中的塊插入資料,當刪除後閥值降到了30%以下才可以往leo6表中的塊插入資料,由此看來,leo7中的塊利用率較高,但IO資源開銷較大,在平時使用時可以根據業務特性結合測試結果靈活設定。

5.設計一個例子,演示資料塊整理(合併)的效果

場合:

1)當insert update操作的行在一個資料塊中有足夠的空閒空間,但這個空閒空間是碎片狀態,又無法滿足一行資料的使用,此時Oracle會自動進行空閒空間合併。

2)空閒空間合併會消耗大量系統資源,只在必要情況下進行手工合併。

3)當我們批次delete刪除記錄時並不會回收HWM高水位線,oracle在掃描表時依然從第一個塊掃描到最後的HWM,掃描時間過長效能下降,在插入新記錄時,也是從HWM之後開始插入,之前標識的刪除記錄所佔用的磁碟空間並沒有釋放,這在磁碟空間較緊張的情況下是不能接受的。我們必須合併那些碎片空間,收集起來迴圈利用,提高磁碟使用率和檢索效率。

4)合併空閒碎片空間的方法有很多,例如 move  rebuild  shrink表等都可實現

shrink表實現合併碎片空間請參考

下面我採用move表方式實現碎片的回收,先介紹一下這種方式的特點

1.不支援線上讀/

2.表在移動的過程中是鎖定狀態不能操作  

3.表在移動後表上索引會失效,必須rebuild重建

4.可以整合碎片

LEO1@LEO1> drop table leo3 purge;                              清空環境

Table dropped.

LEO1@LEO1> create table leo3 as select * from dba_objects;           建立leo3

Table created.

LEO1@LEO1> create index idx_leo3 on leo3(object_id);               建立索引

Index created.

LEO1@LEO1> execute dbms_stats.gather_table_stats(ownname=>'LEO1',tabname=>'LEO3',cascade=>true);

PL/SQL procedure successfully completed.                          做表和索引分析

LEO1@LEO1> select table_name,tablespace_name from user_tables where table_name = 'LEO3';

TABLE_NAME                    TABLESPACE_NAME

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

LEO3                           LEO1

我們建立的leo3表所屬表空間為leo1

LEO1@LEO1> select index_name,table_name,tablespace_name,status from user_indexes where index_name='IDX_LEO3';

INDEX_NAME      TABLE_NAME      TABLESPACE_NAME      STATUS

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

IDX_LEO3          LEO3            LEO1                  VALID

我們建立的idx_leo3索引所屬leo1表空間並且狀態是有效的

LEO1@LEO1> select segment_name,blocks from dba_segments where segment_name='LEO3';

SEGMENT_NAME    BLOCKS

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

LEO3              1152

我們leo3表目前佔用1152個塊

LEO1@LEO1> select count(*) from leo3;                 表中有71968條記錄

  COUNT(*)

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

     71968

LEO1@LEO1> delete from leo3 where rownum<40000;     刪除4w

39999 rows deleted.

LEO1@LEO1> commit;                                提交

Commit complete.

LEO1@LEO1> select count(*) from leo3;                  還剩31969

  COUNT(*)

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

     31969

LEO1@LEO1> select segment_name,blocks from dba_segments where segment_name='LEO3';

SEGMENT_NAME    BLOCKS

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

LEO3              1152

我們現在已經刪除了表中一半資料,但是佔用的資料塊毅然決然是1152個塊,HWM沒有回收,刪除記錄的資料塊沒有釋放,這時候就需要合併釋放空閒空間了。

LEO1@LEO1> select name from v$datafile where rownum=1;     看一下建立表空間路徑

NAME

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

/u01/app/oracle/oradata/LEO1/system01.dbf

LEO1@LEO1> create tablespace new_leo1 datafile '/u01/app/oracle/oradata/LEO1/new_leo1.dbf' size 20m autoextend off;

Tablespace created.

我們建立一個新的表空間new_leo1大小20M非自動擴充套件

LEO1@LEO1> alter table leo3 move tablespace new_leo1;

Table altered.

現在我們把leo3表從leo1表空間movenew_leo3表空間,表在移動的過程中是鎖定狀態不能操作

LEO1@LEO1> select table_name,tablespace_name from user_tables where table_name = 'LEO3';

TABLE_NAME                     TABLESPACE_NAME

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

LEO3                            NEW_LEO1

此時已經把表遷移到了NEW_LEO1表空間

LEO1@LEO1> select index_name,table_name,tablespace_name,status from user_indexes where index_name='IDX_LEO3';

INDEX_NAME      TABLE_NAME      TABLESPACE_NAME      STATUS

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

IDX_LEO3          LEO3            LEO1                  UNUSABLE

表在move後表上的索引會失效,必須rebuild

LEO1@LEO1> select segment_name,blocks from dba_segments where segment_name='LEO3';

SEGMENT_NAME    BLOCKS

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

LEO3              512

見證奇蹟的時刻,leo3表佔用塊數為512個,leo3表經過移動後釋放了一半空間,在資料塊搬家過程中我們從一個碎片奇多的表空間搬到了一個新表空間,資料重新排列杜絕碎片產生。

LEO1@LEO1> alter index idx_leo3 rebuild online;       重建索引

Index altered.

online作用:加online可以在重建索引的過程中對錶進行DML操作,不加online必須等待索引重建完成後才能對錶進行DML操作(在重建過程中鎖定表)

LEO1@LEO1> select index_name,table_name,tablespace_name,status from user_indexes where index_name='IDX_LEO3';

INDEX_NAME      TABLE_NAME      TABLESPACE_NAME      STATUS

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

IDX_LEO3          LEO3            LEO1                  VALID

完美大功告成

extents,blocks,consistent_read,current_read,logical_read,physical_read,pctfree,pctused


2013.4.7
天津&spring
分享技術~成就夢想

Blog

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26686207/viewspace-757937/,如需轉載,請註明出處,否則將追究法律責任。

相關文章