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

从以上结果看出,统计信息收集是否正确,对执行计划影响是非常大的。


你可能感兴趣的:(Oracle)