全部的 oracle 段(segments,在此,爲了理解方便,建議把 segment 做爲表的一個同義詞) 都有一個在段內容納數據的上限,咱們把這個上限稱爲"high water mark"或 HWM。這個 HWM 是一個標記,用來講明已經有多少沒有使用的數據塊分配給這個 segment。HWM 一般增加的幅度爲一次5個數據塊,原則上 HWM 只會增大,不會縮小,即便將表中的數據所有刪除,HWM 仍是爲原值,因爲這個特色,使 HWM 很象一個水庫的歷史最高水位,這也就是 HWM的原始含義,固然不能說一個水庫沒水了,就說該水庫的歷史最高水位爲0。可是若是咱們在表上使用了 truncate命令,則該表的 HWM 會被從新置爲0.數據庫
a) 全表掃描一般要讀出直到 HWM 標記的全部的屬於該表數據庫塊,即便該表中沒有任何數據。oracle
b) 即便 HWM 如下有空閒的數據庫塊,鍵入在插入數據時使用了 append 關鍵字,則在插入時使用 HWM 以上的數據塊,此時 HWM 會自動增大app
- a) 首先對錶進行分析:
ANALYZE TABLE <tablename> ESTIMATE/COMPUTE STATISTICS;b) SELECT blocks, empty_blocks, num_rowsFROM user_tablesWHERE table_name = <tablename>; ---說明:BLOCKS 列表明該表中曾經使用過得數據庫塊的數目,即水線。EMPTY_BLOCKS 表明分配給該表,可是在水線以上的數據庫塊,即歷來沒有使用的數據---讓咱們以一個有28672行的 BIG_EMP1表爲例進行說明: 1) SQL> SELECT segment_name, segment_type, blocksFROM dba_segmentsWHERE segment_name='BIG_EMP1'; SEGMENTNAME SEGMENTTYPE BLOCK ----------------- -------------- --------- BIG_EMP1 TABLE 1024 1 row selected. 2) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;Statement processed. 3) SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='BIG_EMP1'; TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOC ---------- -------- ------- ------------- BIG_EMP1 28672 700 323 1 row selected. ---注意:BLOCKS + EMPTY_BLOCKS (700+323=1023)比 DBA_SEGMENTS.BLOCKS 少1個數據庫塊,這是由於有一個數據庫塊被保留用做 segment header。DBA_SEGMENTS.BLOCKS 表示分配給這個表的全部的數據庫塊的數目。USERTABLES.BLOCKS 表示已經使用過的數據庫塊的數目。 4) SQL> SELECT COUNT (DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"FROM big_emp1; Used ---------- 700 1 row selected 5) SQL> delete from big_emp1;28672 rows processed. 6) SQL> commit;Statement processed. 7) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;Statement processed. 8) SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='BIG_EMP1'; TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS --------- -------- ------- ---------- BIG_EMP1 0 700 323 1 row selected. 9) SQL> SELECT COUNT (DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"FROM big_emp1; Used ---------- 0 -----這表名沒有任何數據庫塊容納數據,即表中無數據1 row selected. 10) SQL> TRUNCATE TABLE big_emp1; Statement processe 11) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS; Statement processed. 12) SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='BIG_EMP1'; TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS ---------- -------- -------- ------------ BIG_EMP1 0 0 511 1 row selected. 13) SQL> SELECT segment_name,segment_type,blocksFROM dba_segmentsWHERE segment_name='BIG_EMP1'; SEGMENT_NAME SEGMENT_TYPE BLOCKS ------------ ------------- ------ BIG_EMP1 TABLE 512 1 row selecte -----TRUNCATE 命令回收了由 delete 命令產生的空閒空間,注意該表分配的空間由原先的1024塊降爲512塊。爲了保留由 delete 命令產生的空閒空間,可使用 TRUNCATE TABLE big_emp1 REUSE STORAGE.用此命令後,該表還會是原先的1024
在 Oracle 數據的存儲中,能夠把存儲空間想象爲一個水庫,數據想象爲水庫中的水。水庫中的水的位置有一條線叫作水位線,在 Oracle 中,這條線被稱爲高水位線(High-warter mark, HWM)。在數據庫表剛創建的時候,因爲沒有任何數據,因此這個時候水位線是空的,也就是說 HWM 爲最低值。當插入了數據之後,高水位線就會上漲,可是這裏也有一個特性,就是若是你採用 delete 語句刪除數據的話,數據雖然被刪除了,可是高水位線沒有下降,仍是剛剛刪除數據之前的那麼高的水位線。也就是說:這條水位線在平常的增刪操做中只會上漲,不會下跌。性能
下面咱們來談一下 Oracle 中 Select 語句的特性。Select 語句會對錶中的數據進行一次掃描,可是究竟掃描多少數據存儲塊呢,這個並非說數據庫中有多少數據,Oracle 就掃描這麼大的數據塊,而是 Oracle 會掃描高水位線如下的數據塊。如今來想象一下,若是剛纔是一張剛剛創建的空表,你進行了一次 Select 操做,那麼因爲高水位線 HWM 在最低的0位置上,因此沒有數據塊須要被掃描,掃描時間會極短。而若是這個時候你首先插入了一千萬條數據,而後再用 delete 語句刪除這一千萬條數據。因爲插入了一千萬條數據,因此這個時候的高水位線就在一千萬條數據這裏。後來刪除這一千萬條數據的時候,因爲 delete 語句不影響高水位線,因此高水位線依然在一千萬條數據這裏。這個時候再一次用 select 語句進行掃描,雖然這個時候表中沒有數據,可是因爲掃描是按照高水位線來的,因此須要把一千萬條數據的存儲空間都要掃描一次,也就是說此次掃描所須要的時間和掃描一千萬條數據所須要的時間是同樣多的。因此有時候有人老是常常說,怎麼個人表中沒有幾條數據,可是仍是這麼慢呢,這個時候其實奧祕就是這裏的高水位線了。
那有沒有辦法讓高水位線降低呢,其實有一種比較簡單的方法,那就是採用 TRUNCATE 語句進行刪除數據。採用TRUNCATE 語句刪除一個表的數據的時候,相似於從新創建了表,不只把數據都刪除了,還把 HWM 給清空恢復爲0。因此若是須要把表清空,在有可能利用 TRUNCATE 語句來刪除數據的時候就利用 TRUNCATE 語句來刪除表,特別是那種數據量有可能很大的臨時存儲spa
在手動段空間管理(Manual Segment Space Management)中,段中只有一個 HWM,可是在 Oracle9iRelease1才添加的自動段空間管理(Automatic Segment Space Management)中,又有了一個低 HWM 的概念出來。爲何有了 HWM 還又有一個低 HWM 呢,這個是由於自動段空間管理的特性形成的。在手段段空間管理中,當數據插入之後,若是是插入到新的數據塊中,數據塊就會被自動格式化等待數據訪問。而在自動段空間管理中,數據插入到新的數據塊之後,數據塊並無被格式化,而是在第一次在第一次訪問這個數據塊的時候才格式化這個塊。因此咱們又須要一條水位線,用來標示已經被格式化的塊。這條水位線就叫作低 HWM。通常來講,低 HWM 確定是低於等於HWM 的。 日誌
在 ORACLE 中,執行對錶的刪除操做不會下降該表的高水位線。而全表掃描將始終讀取一個段(extent)中全部低於高水位線標記的塊。若是在執行刪除操做後不下降高水位線標記,則將致使查詢語句的性能低下。下面的方法均可以下降高水位線標記。code
1.執行表重建指令 alter table table_name move;blog
(在線轉移表空間 ALTER TABLE 。。。 MOVE TABLESPACE 。。。ALTER TABLE 。。。 MOVE 後面不跟參數也行,不跟參數表仍是在原來的表空間,move 後記住重建索引。若是之後還要繼續向這個表增長數據,沒有必要 move,只是釋放出來的空間,只能這個表用,其餘的表或者 segment 沒法使用該空間)索引
2.執行 alter table table_name shrink space; get
注意,此命令爲 Oracle 10g 新增功能,再執行該指令以前必須容許行移動 alter table table_name enable row movement;
實質上構造一個新表(在內部表現爲一系列的 DML 操做,即將副本插入新位置,刪除原來位置的記錄)靠近末尾處(右端)數據塊中的記錄往開始處(左端)的空閒空間處移動(DML 操做),不會引發 DML 觸發器當全部可能的移動被完成,高水位線將會往左端移動(DDL 操做)
新的高水位線右邊的空閒空間被釋放(DDL 操做)
實現前提條件:必須啓用行記錄轉移(enable row movement)僅僅適用於堆表,且位於自動段空間管理的表空間(堆表包括:標準表,分區表,物化視圖容器,物化視圖日誌表)3.複製要保留的數據到臨時表 t,drop 原表,而後 rename 臨時表 t 爲原表
4.emp/imp
5.alter table table_name deallocate unused
6.儘可能 truncate
=========================================================================================