高水位线

一.oracle的逻辑存储管理

oracle在逻辑存储上分四个粒度:表空间,段,区和块

1.块:是粒度最小的存储单位,标准块的大小是8k,oracle每一次io操作也是按块来进行

就是说,oracle从数据文件读取数据时,是读取多少个块,而不是多少行.每一个block

里面有可能包含掉个row.

2.区:由一系列相邻的块组成,是oracle空间分配的基本单位,例如,当创建一个表时,首先

oracle会分配一区的空间给这个表,随着对这个表的insert操作,原来的空间容不下插入的

数据的时候,oracle就会以区为单位进行扩展,也就是说再分配多少个区给这个表,而不是

多少个块。

3.段:是由一系列的区组成,一般来说,当创建一个对象时(对象,索引),就会分配一个段给

这个对象,例如create ttable tab_1,这个段就是数据段,而create index on tab1(id),oracle同样

会分配一个段给这个索引,就是一个索引段,查询段的信息sql:

select * from user_segments

4.表空间;包含段,区及块,表空间的数据存储在其所在的数据文件中。一个数据库至少要有

一个表空间

else:

当创建一个表,且没有插入任何一行记录,oracle还是会给他分配8个块,也就说,在这个对象创建以后,oracle至少给他分配一个区

初始大小是64k,一个标准块的大小是8k,刚好是8个block


二.高水位线(high water mark)

1.oracle表段中的高水位线

  oracle数据的存储类似于水库,数据可以视为水库中的水,水位线也就是orcle中所成的高水位线

在数据库房间里,水位线是空的,也就是HWM为最低值,当插入数据,水位线就会上涨。这里面

有一个特性,当采用delete语句删除数据时,数据虽然被删除,但HWM并没有降低。也就是说,在

日常的增删操作中,高位谁先只会上涨,不会下跌。HWM通常增长的幅度为一次5个数据块。

  select语句会对表中的数据进行扫描,扫描多少数据存储块并不是取决于数据库中有多少数据,而是

会扫描高水位线一下的数据。由于delete语句不会降低高水位线,当表中其实没有多少数据时,也会因为

高水位线的原因导致查询效率比较低。

else:

低水位线概念:在手动段管理中,当数据插入后,如果是插入到新的数据块中,数据块就会被自动格式化

等待数据访问。而在自动段管理中,数据插入到新的数据块以后,数据块并没有被格式化,而是在第一次

访问这个数据块的时候才格式化这个块。所以就又需要一条水位线来标识已经被格式化的block.这条水位线

就叫做低水位线


三.高水位线修正

  在oracle中,执行对表的操作不会降低该表的高水位线。而全表扫描将始终读取一个段(extent)中所有低于

高水位线标记的块,如果在执行delete操作后不降低高水位线标记,将导致查询语句的性能低下


a.执行表重建命令

alter table table_name move;

案例:

INSERT INTO t2 SELECT * FROM all_objects ;

ANALYZE TABLE T2 ESTIMATE STATISTICS;

SELECT A.TABLE_NAME, A.NUM_ROWS, A.BLOCKS, A.EMPTY_BLOCKS
  FROM USER_TABLES A;

TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
1 T2 77287 1126 26

DELETE FROM T2;

ANALYZE TABLE T2 ESTIMATE STATISTICS;

SELECT A.TABLE_NAME, A.NUM_ROWS, A.BLOCKS, AT4.EMPTY_BLOCKS
  FROM USER_TABLES A;

ALTER TABLE T2 MOVE;

ANALYZE TABLE T2 ESTIMATE STATISTICS;

SELECT A.TABLE_NAME, A.NUM_ROWS, A.BLOCKS, A.EMPTY_BLOCKS
  FROM USER_TABLES A;

b.执行表收缩命令

案例:

--高水位线
CREATE TABLE test1 TABLESPACE tbs1 AS SELECT * FROM all_objects ;


TRUNCATE TABLE test1;


INSERT INTO test1 SELECT * FROM all_objects;


ANALYZE TABLE test1 ESTIMATE STATISTICS;


SELECT blocks,empty_blocks,num_rows FROM user_tables WHERE table_name='TEST1';


DELETE FROM TEST1;


ALTER TABLE TEST1 ENABLE ROW MOVEMENT;


ALTER TABLE TEST1 SHRINK SPACE CASCADE;

重新查询后对比


c.重建表

案例:

CREATE TABLE tmp AS SELECT * FROM T3 ;

DROP TABLE t3;

RENAME  tmp TO t3;

d.使用逻辑导入导出:EMP/IMP

案例:

DELETE FROM t4;
ANALYZE TABLE t4 ESTIMATE STATISTICS;
SELECT a.TABLE_NAME,a.NUM_ROWS,a.BLOCKS,a.EMPTY_BLOCKS FROM user_tables A WHERE table_name='T4';
[oracle@redhat5 ~]$ exp scott/oracle file='/home/oracle/t4.dmp' tables=T4;
SQL> conn scott/oracle
Connected.
SQL> drop table t4;
[oracle@redhat5 ~]$ imp scott/oracle file='/home/oracle/t4.dmp' tables=T4;
SQL> analyze table t4 estimate statistics;
Table analyzed.
SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T';
TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T                                       0          1            7

e.alter table table_name deallocate unused

deallocate unused为释放高水位线上面的未使用空间,但是并不会释放HWM下面的自由空间,也不会移动HWM的位置

案例:

DELETE FROM t5;
ANALYZE TABLE T5 ESTIMATE STATISTICS ;
SELECT TABLE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS FROM USER_TABLES WHERE TABLE_NAME='T5';
ALTER TABLE T5 DEALLOCATE UNUSED ;
SELECT TABLE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS FROM USER_TABLES WHERE TABLE_NAME='T5';

f.truncate(推荐使用)


四.高水位线特点


1.oracle使用hwm来界定一个段中使用的块和未使用的块

  当创建一个表时,oracle为这个对象分配一个段,在这个段中,即时未插入任何记录,也至少有一个区被分配。第一个

区的第一个块就称为段头(segment header),端头中存储的信息就包括HWM的信息

  此时,因为第一个区的第一个block用于存储端头的信息,虽然没有存储任何的实际记录,但也算是被使用,此时HWM

位于第2个块。当不断插入数据,第一个块已经放不下新插入的数据,此时,oracle将HWM之上的块用于存储新增数据,同

时高水位线本身也向上移,这样,HWM不断的上移,栽HWM之下的就代表使用过的块,HWM之上的就代表已分配但

还未使用过的块。


2.HWM在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会向下移

  oracle不会释放空间以供其他对象使用,可以简单的解释为:由于空间是为新插入的行保留的,并且要适应现有行的增长。

被占用的最高空间就被成为最高使用标记。


3.HWM的信息存储在段头中

  当段空间是手工管理时,oracle是通过freelist(一个单向链表)来管理段内的空间分配,在段空间是自动管理时,oracle是通过BITMAP

来管理段内的空间分配


4.oracle的全表扫描是读取高水位线标记一下的所有块.


5.当使用直接路径插入行时,即时HWM以下有空闲的数据库块,加入在插入的时候使用了apppend关键字,则

在插入时,使用hwm以上的数据块。此时hwm会自动增大。

  也就是说,通过直接加载插入(append)或通过sql*loader直接

将数据块置于HWM之上。hwm下面的空间就会被直接浪费掉

你可能感兴趣的:(高水位线)