1. 程式人生 > >12_Delete不釋放高水位線的問題,與truncate對比實驗

12_Delete不釋放高水位線的問題,與truncate對比實驗

Delete不釋放高水位線的問題,與truncate對比實驗

Oracle高水位線 HWM對資料庫影響:

1. 全表掃描通常要讀取直到HWM標記內,所有屬於該表資料庫塊,即使該表中沒有任何資料,這樣將耗費更多的I/O資源;

2. 即使HWM以下有空閒的資料庫塊,鍵入在插入資料時使用了append關鍵字,則在插入時使用HWM以上的資料塊,此時HWM會自動增大;

3. 優點,可使HWM以下的資料塊重複利用。

----實驗-----------------------------------------------------------------------

1. 建表

Create table test_0412 as

select * from user_objects;

2. 檢視統計資訊

select t.BLOCKS, t.NUM_ROWS

  from user_tables t

 where t.TABLE_NAME = 'TEST_0412';

結果為空,說明系統沒有收集到統計資訊。

檢視段資訊:

select blocks from user_segments where segment_name='TEST_0412';

--結果說明資料已儲存至段:

BLOCKS   8

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

Select * from test_0412;

沒有統計資訊情況下,看執行計劃,走的全表掃描,邏輯讀為1,物理讀為38,如下:

Execution Plan

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

Plan hash value: 3552262383

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

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |           |    41 |  7790 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| TEST_0412 |    41 |  7790 |     3   (0)| 00:00:01 |

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

Note

-----

   - dynamic sampling used for this statement (level=2)

Statistics

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

        288  recursive calls

          0  db block gets

         38  consistent gets

          1  physical reads

          0  redo size

       5210  bytes sent via SQL*Net to client

        545  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

         41  rows processed

3. 收集統計資訊

SQL> Exec dbms_stats.gather_table_stats(user,'TEST_0412');

PL/SQL procedure successfully completed.

4. 二次檢視統計資訊是否收整合功

select t.BLOCKS, t.NUM_ROWS

  from user_tables t

 where t.TABLE_NAME = 'TEST_0412';

結果:

BLOCKS      4

NUM_ROWS  41

---

檢視段資訊:

select blocks from user_segments where segment_name='TEST_0412';

--結果說明統計資訊收集對段無影響:

BLOCKS   8

---

alter session set events 'immediate trace name flush_cache';--清空快取

Select * from test_0412;

看執行計劃,走全表掃描,邏輯讀為2,物理讀為6,如下:

Execution Plan

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

Plan hash value: 3552262383

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

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |           |    41 |  3075 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| TEST_0412 |    41 |  3075 |     3   (0)| 00:00:01 |

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

Statistics

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

          0  recursive calls

          0  db block gets

          6  consistent gets

          2  physical reads

          0  redo size

       5210  bytes sent via SQL*Net to client

        545  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

         41  rows processed

5. Delete資料,清空表

delete from TEST_0412;

Commit;

SQL> Exec dbms_stats.gather_table_stats(user,'TEST_0412');

PL/SQL procedure successfully completed.

6. 三次檢視統計資訊

select t.BLOCKS, t.NUM_ROWS

  from user_tables t

 where t.TABLE_NAME = 'TEST_0412';

結果:

BLOCKS      4

NUM_ROWS  41

---

檢視段資訊:

select blocks from user_segments where segment_name='TEST_0412';

--結果說明段無影響:

BLOCKS   8

---

證明了Delete操作沒有更新高水位線,即沒有更新段資訊。

Oracle全表掃描的機制:掃描HWM(高水位線)下的所有資料塊,而delete操作不會釋放高水位線。

同問,Truncate操作可以更新高水位線嗎?可參看第8步驟操作

7. 查詢全表,看執行計劃,是否全表掃描,邏輯讀和物理讀是多少?

雖然結果是0行,但還是有邏輯讀、物理讀等消耗,如下:

SQL> select * from test_0412;

no rows selected

Execution Plan

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

Plan hash value: 3552262383

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

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |           |    41 |  3075 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| TEST_0412 |    41 |  3075 |     3   (0)| 00:00:01 |

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

Statistics

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

          0  recursive calls

          0  db block gets

          3  consistent gets

          2  physical reads

          0  redo size

       1276  bytes sent via SQL*Net to client

        512  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          0  rows processed

8. Truncate操作可以更新高水位線嗎?

truncate table TEST_0412;

SQL> Exec dbms_stats.gather_table_stats(user,'TEST_0412');

PL/SQL procedure successfully completed.

select t.BLOCKS, t.NUM_ROWS

  from user_tables t

 where t.TABLE_NAME = 'TEST_0412';

--結果已重新收集:

BLOCKS      0

NUM_ROWS  0

---

檢視段資訊:

select blocks from user_segments where segment_name='TEST_0412';

--結果說明Truncate對段無影響:

BLOCKS   8

結果證明truncate操作可更新高水位線HWM

9. 如何降低高水位線?

alter table TEST_0412 move; --move壓縮高水位線HWM以下的空間,消除碎片,move操作後需對索引rebuild

Exec dbms_stats.gather_table_stats(user,'TEST_0412');

select t.BLOCKS, t.NUM_ROWS

  from user_tables t

 where t.TABLE_NAME = 'TEST_0412';

--結果重新收集:

BLOCKS      0

NUM_ROWS  0

---

檢視段資訊:

select blocks from user_segments where segment_name='TEST_0412';

--結果段無影響:

BLOCKS   8

10. 再次查詢全表,看執行計劃,是否全表掃描,邏輯讀和物理讀

SQL> alter session set events 'immediate trace name flush_cache'; --清空快取

SQL> select * from test_0412;

no rows selected

Execution Plan

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

Plan hash value: 3552262383

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

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |           |     1 |   190 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| TEST_0412 |     1 |   190 |     2   (0)| 00:00:01 |

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

Statistics

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

          0  recursive calls

          0  db block gets

          3  consistent gets

          1  physical reads

          0  redo size

       1276  bytes sent via SQL*Net to client

        512  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          0  rows processed

從以上結果看出,統計資訊收集是否正確,對執行計劃影響是非常大的。