上一篇博客中提到,當我們用delete刪除數據時,因為無法降低高水位,對表做全表掃描時會帶來數據庫性能問題,而truncate可以大大改善這一狀況,下面來看測試
SQL> conn zlm/zlm
Connected.
--創建表之前先記錄下剩余表空間大小
SQL> select * from dba_free_space where tablespace_name='ZLM';
TABLESPACE_NAME FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
------------------------------ ---------- ---------- ---------- ---------- ------------
ZLM 6 128 51380224 6272 6
--創建一個100W行的大表
SQL> create table test1(int number);
Table created.
SQL> analyze table test1 compute statistics;
Table analyzed.
SQL> select table_name,num_rows,blocks,empty_blocks,avg_row_len,last_analyzed from dba_tables where table_name like 'TEST%';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_ROW_LEN LAST_ANALYZED
------------------------------ ---------- ---------- ------------ ----------- ------------------
TEST1 0 0 0 0 27-SEP-14
注意,創建完表結構而未插入數據時,表的高水位是0,并沒有為該表分配任何數據塊
SQL> declare
SQL> set autot trace
SQL> select count(*) from test1;
Execution Plan
----------------------------------------------------------
Plan hash value: 3896847026
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TEST1 | 1 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
1 db block gets
1599 consistent gets
0 physical reads
0 redo size
526 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> delete from test1;
1000000 rows deleted.
Execution Plan
----------------------------------------------------------
Plan hash value: 2642947686
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | DELETE | TEST1 | | | |
| 2 | TABLE ACCESS FULL| TEST1 | 1 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------
Statistics
----------------------------------------------------------
814 recursive calls
1038983 db block gets
1953 consistent gets
8 physical reads
245334988 redo size
847 bytes sent via SQL*Net to client
769 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1000000 rows processed
用delete刪除100W行數據的大表TEST1時,產生了大量的redo(2億多),另外還有很多一致性讀(1953),讀取了100多W個數據塊,814次遞歸調用,可以看到,用delete刪除表記錄,對數據庫的性能消耗是很大的,尤其是當delete大量行的時候
SQL> set autot off
SQL> select count(*) from test1;
COUNT(*)
----------
0
SQL> select header_file,header_block,bytes,blocks,extents from dba_segments where segment_name like 'TEST%';
HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS
----------- ------------ ---------- ---------- ----------
6 130 13631488 1664 28
--用delete刪除數據后查看執行計劃
SQL> set autot trace
SQL> select count(*) from test1;
Execution Plan
----------------------------------------------------------
Plan hash value: 3896847026
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TEST1 | 1 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
1 db block gets
1599 consistent gets
0 physical reads
0 redo size
525 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
此時雖然表中已經沒有一條記錄了,但是由于TEST1表并沒有索引,走的是全表掃描,全表掃描就是要從hearder_block的值一致掃描到blocks得值,即從block 130一致到block 1664,可以看到,即使去訪問一個空表,也要消耗1599次邏輯讀,這就是高水位沒有下降的緣故,之前說過,delete操作并不會降低表的高水位,帶來的副作用就是訪問該表時帶來的性能下降(產生大量邏輯讀)
--truncate表后再次查看統計信息
SQL> truncate table test1;
Table truncated.
SQL> set autot trace
SQL> select count(*) from test1;
Execution Plan
----------------------------------------------------------
Plan hash value: 3896847026
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TEST1 | 1 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------
Statistics
----------------------------------------------------------
2 recursive calls
1 db block gets
7 consistent gets
0 physical reads
96 redo size
525 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
此時再去全表掃描TEST1表,只有7次一致性讀了,大大降低了需要掃描的數據庫塊,只有1個,
--查看此時TEST1表的表信息
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈