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
從以上結果看出,統計資訊收集是否正確,對執行計劃影響是非常大的。