在讨论高水位之前需要明确一下oracle的逻辑存储的概念:Block、extent、segment、tablespace
block:块的概念,他是oracle最小的一个存储单元,一般为8K,也是一次io的最基本操作单位。
extent:区的概念,他是由一组连续的block组成的,他是oracle空间分配的基本单位。
segment:段的概念,是有一系列extent组成的,一般说你创建一个对象时,会分配一个段给这个对象,所以我们都会抽象一个表或者一个索引为一个表段或者索引段。
tablespace:包含段,区及块,表空间的数据物理上存储在数据文件里。
oracle段上的HWM是一个标记,标记已经有多少没有使用的数据库分配给这个segment。原则上HWM智慧增加,不会缩小,即使将表的数据全部删除,HWM还是原来的值。truncate命令,会重置HWM为0.
1、讲完了oracle的逻辑存储的概念,接下来我们来模拟创建一张表,并且不插入数据,看看他分配了多少个数据块。
SQL> create table tt(id number);
Table created.
SQL> select segment_name,segment_type,blocks from user_segments where segment_name = 'TT';
no rows selected
我们惊奇的发现在user_segments视图里面是查不到这张表的,这里就引出了11GR2版本的延迟段创建,官方的解释如下:
The initial segment creation for nonpartitioned tables and indexes can be delayed until data is first inserted into an object.
因为很多数据库都有存在空表的情况,较多的空表会占用大量的磁盘空间,所谓延迟段创建,顾名思义就是在创建一张新空表的时候,ORACLE默认不会为这张空表分配段(SEGMENTS),也就是不会为这张空表分配空间,这样就避免了空表占用空间的情况
2、然后我们向这张TT表里插入10000条数据
declare
i number;
begin
for i in 1..10000 loop
insert into tt values(i);
end loop;
commit;
end;
/
select owner,segment_name,segment_type,blocks from dba_segments where segment_name = 'TT';
OWNER SEGMENT_NAME SEGMENT_TYPE BLOCKS
------- ------------- ------------- ------
SCOTT TT TABLE 128
此时TT占用了数据库128个block了,还记得一般插入大量数据的时候,需要收集统计信息的事儿吗?
SQL> exec dbms_stats.gather_table_stats('scott','tt');
PL/SQL procedure successfully completed.
select owner,segment_name,segment_type,blocks from dba_segments where segment_name = 'TT';
OWNER SEGMENT_NAME SEGMENT_TYPE BLOCKS
------- ------------- ------------- ------
SCOTT TT TABLE 128
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 10000 60 0
我们可以看到现在user_tables里面显示了,这个表现在已经使用了60个block,可是我们之前已经分配了128个block,可是这里面的empty_block可是为0啊,这又是为什么呢?
SQL> analyze table tt compute statistics;
Table analyzed.
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 10000 60 68
这里需要解释的就是analyze table ** compute statistics也是一种收集统计信息的方式,后来出现了dbms_stats包逐渐取代了analyze的地位。但是有些操作只有analyze只能做,比如刚才的操作。
通过收集统计信息,可以看到empty_block为68个,与60一起正好128吧,跟之前的查询结果相匹配。
3、delete数据的时候,看看是不是会降低高水位
SQL> delete from tt;
10000 rows deleted.
SQL> commit;
Commit complete.
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 10000 60 68
SQL> select owner,segment_name,segment_type,blocks from user_segments where segment_name = 'TT';
OWNER SEGMENT_NAME SEGMENT_TYPE BLOCKS
------- ------------- ------------- ------
SCOTT TT TABLE 128
SQL> analyze table tt compute statistics;
Table analyzed.
SQL> select owner,segment_name,segment_type,blocks from dba_segments where segment_name = 'TT';
OWNER SEGMENT_NAME SEGMENT_TYPE BLOCKS
------- ------------- ------------- ------
SCOTT TT TABLE 128
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 0 60 68
我们发现delete根本不会降低高水位(HWM)
4、验证truncate表,是否会降低高水位
SQL> truncate table tt;
Table truncated.
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 0 60 68
SQL> select segment_name,segment_type,blocks from user_segments where segment_name = 'TT';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------- ------------------ ----------
TT TABLE 128
我们发现段的信息也是没有改变的,那么我们收集一下统计信息来看看
SQL> exec dbms_stats.gather_table_stats('scott','tt');
PL/SQL procedure successfully completed.
SQL> select segment_name,segment_type,blocks from user_segments where segment_name = 'TT';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
--------------- ------------------ ----------
TT TABLE 128
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 0 0 68
段的信息已经改变了,但是empty_block并没有改变,还是需要我们analyze来分析一下
SQL> analyze table tt compute statistics;
Table analyzed.
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name = 'TT';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
TT 0 0 128
我们现在可以看到empty_block是128个。