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
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 ;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下面的空间就会被直接浪费掉