資料庫的邏輯儲存結構也可以叫做儲存層次體系,ORACLE的儲存層次體系按照層次從高到低分為:表空間(tablespace)、段(segment)、區(extent)、塊(block)。熟悉資料庫的邏輯儲存結構可以幫助我們分析與定位資料庫的空間容量問題。
一、段
段是表空間的主要組織結構。段就是佔用儲存空間的資料庫物件,比如建立表時,會建立一個表段;建立索引時,會建立一個索引段;建立分割槽表時,會為每個分割槽建立一個段。此外還有回滾段、臨時段等。透過查詢dba_segments檢視可以檢視資料庫中段的大小,進而知道表、索引等物件的大小。
二、區
段由一個或多個區組成,區是檔案中一個邏輯上連續分配的空間。在ORACLE中有“延遲段”的概念,即當你建立物件時,ORACLE不會為段分配一個新的區,而是當資料真正寫入時,ORACLE才會為這個段分配第一個區,當初始的區不足以容納新增資料時,ORACLE就會為它再分配一個區。這兩個區在物理上不一定是連續的,但是在邏輯上是連續的。區的大小可能只是一個資料塊,也可能大到幾GB。
三、塊
區進一步由塊組成,塊也是ORACLE中最小的空間分配單位,行資料就儲存在塊中。塊也是磁碟IO的基本單位,ORACLE中常見的塊有2kb、4kb、8kb、16kb。在ORACLE中,db_block_size引數指定了資料庫的預設塊大小,其值取決於作業系統,一般是8kb。此外,也可以在建立表空間時自定義資料塊大小。
四、表空間
表空間是一個容器,一個表空間中可能有多個段。前面說到的段、區、塊都是不同層次的邏輯儲存單位,從物理上看資料庫的資料看是放在資料檔案中,在ORACLE中透過表空間管理資料檔案,一個表空間可由多個資料檔案組成。可以看到在資料目錄下,*.dbf檔案就是表空間檔案,有system01.dbf和sysaux01.dbf兩個系統表空間,users01.dbf使用者表空間,undotbs01.dbf回滾表空間,temp01.dbf臨時表空間,這也是系統中預設建立的幾個表空間。
在實際生產應用中,我們一般會額外建立表空間存放應用資料,並且在建立使用者時指定該使用者的預設表空間。一般常用的建立表空間的語句如下:
create tablespace app_data_tbs datafile '/u01/oracle/oradata/orcl/app_data_tbs01.dbf' size 8g autoextend on next 100m; create tablespace app_idx_tbs datafile '/u02/oradata/tyzh/app_idx_tbs01.dbf' size 8g autoextend on next 100m;
該語句定義了表空間的大小,並且設定該表空間以100M的幅度自動增長。那麼表空間最大可以增長到多少呢?這和表空間中資料檔案的容量有關,通常ORACLE的物理檔案最大隻允許4194303個資料塊(由作業系統決定),那麼表空間資料檔案的最大值為4194303×DB_BLOCK_SIZE/1024M,當DB_BLOCK_SIZE為8k時,這個表空間資料檔案的最大值為32G。我們在資料庫中建立一個33G的表空間,可以看到該語句報錯超過了最大的block數量4194303。所以,當表空間達到最大值時,我們只能透過增加資料檔案的方法對錶空間進行擴容。
alter tablespace app_data_tbs add datafile '/u01/oracle/oradata/orcl/app_data_tbs02.dbf' size 1g autoextend on next 100m;
查詢表空間的使用資訊可以透過dba_tablespaces、dba_data_files、dba_free_space等資料字典檢視查詢,以下是幾個常用的查詢表空間使用情況的指令碼:
#檢視錶空間大小 select t.tablespace_name, round(sum(bytes/(1024*1024)),0) ts_size from dba_tablespaces t, dba_data_files d where t.tablespace_name = d.tablespace_name group by t.tablespace_name; #檢視錶空間資料檔案大小 select tablespace_name, file_id, file_name, round(bytes/(1024*1024),0) total_space from dba_data_files order by tablespace_name; #檢視錶空間剩餘容量 select sum(bytes)/(1024*1024) as free_space,tablespace_name from dba_free_space group by tablespace_name #檢視錶空間使用率 select total.tablespace_name,round(total.MB, 2) as Total_MB,round(total.MB - free.MB, 2) as Used_MB,round((1-free.MB / total.MB)* 100, 2) || '%' as Used_Pct from (select tablespace_name, sum(bytes) /1024/1024 as MB from dba_free_space group by tablespace_name) free,(select tablespace_name, sum(bytes) / 1024 / 1024 as MB from dba_data_files group by tablespace_name) total where free.tablespace_name = total.tablespace_name order by used_pct desc;