Oracle 原理:高水位线、PCTFREE、PCTUSED、索引组织表、簇表、临时表

目录

1.11g中表的类型:

2.高水位线HWM,(High Water Mark)

3.PCTFREE 和PCTUSED;

4. move、shrink、truncate来降低高水位线

5.IOT表、簇表、临时表


1.11g中表的类型:

普通表、分区表、索引组织表IOT、簇表、临时表、嵌套表、对象表等。

分区表:为了提高容纳的数据量和查询速度把一个表分在多个区上。簇表:使联合查询时变得快。适用于频繁关联查询的表。嵌套表:表中有表,比如的表A中某行某列是表B的数据,像"盒子"一样的包含关系,就叫嵌套表。

2.高水位线HWM,(High Water Mark)

高水位线是指的是在 表中数据块的历史最大使用数量。高水位线一般是不会降低的。除非使用rebuild重建,truncated截断,shrunk收缩才会刷新高水位线。 

  全表扫描时,就是从表中的第0个数据块开始,一个数据块一个数据块的扫描到高水位线。也就是说,如果表中没有任何数据,也会要扫描到高水位线的数据块位置。

刚开始创建表是高水位线位于0号数据块位置,然后不断地插入数据,高水位线因此上升,然后把数据删除,高水位线依旧不变,如上图。

3.PCTFREE 和PCTUSED;

一个数据块大小默认为8KB,而PCTFREE(默认10%)指定了一个数据块中插入数据允许的最小空闲内存占比。而PCTUSED(默认40%)指定了一个数据块中允许重新插入数据的内存占比,单位为%。当往表中插入数据时,不会把数据块放满,因为这个空闲内存是为了给修改数据做准备的。加入insert数据块把数据块放满了后,再update数据内容,内容减小还好说,内容变多,当前数据块就没有可用的内存来给数据扩展了。数据块包含了3部分:数据块头(Header)、空闲内存(Free Space)、数据(DATA); PCTFREE控制着Free Space的最小值,超过则不准再插入,允许删除。PCTUSED控制着DATA的最小值,超过则恢复允许插入。不是说PCTFREE设了20%空间区域就永远大于20%,而是说空闲区域至少留20%将来给Oracle做数据扩展用的。一个数据块可以放表中的多个行数据。

 结合上图所示。当一个数据块被启用时,数据块使用率从0%开始上升,未使用率从100%开始下降。假如PCTFREE设成20%,PCTUSED设成40%。由于刚开始数据块的使用率小于PCTUSED,所以允许往数据块中插入数据,直到未使用率达到FreeSpace变成了20%就不准在往此数据块中插入数据了,想要再往这个数据块中插入数据,就要把数据块使用率下降到PCTUSED 40%才被允许。

如果数据依旧超出了数据块总大小,将用行迁移的方式:Oracle会把原来数据块上的行数据头(Row-Header)保留,后面跟个C++一样的指针,把数据Data迁移到新的数据块上,让指针指向这数据。

数据块大小默认 8KB ,如果一个数据行大小超出了内存中最大可用的数据块大小,将会发生行链接:将一笔数据放入不同的数据块中,用指针的方式将同一笔数据关联起来。

如果表空间上指定了ASSM时,建表时只能指定PCTFREE。ASSM,自动段空间管理。MSSM,手动段空间管理。

查看是否段空间管理: select s.TABLESPACE_NAME,s.SEGMENT_SPACE_MANAGEMENT from dba_tablespaces s;

表空间扩展:alter table voapd.t1 allocate extent(datafile 'D:\ORACLE\ORADATA\ORCL\TESTTBS.DBF' size 1m);

4. move、shrink、truncate来降低高水位线

  move 语句,将表中的数据移动到另一个表空间上,同时会清除表空间碎片和降低高水位线:

  alter table [表名] move [tablespace USERS];

为了理解高水位线,首先创建一张表t2:

------之前创建了表空间 TESTTBS;
create table t2 tablespace TESTTBS as select * from dba_objects; --count(*)=72092

之后可以分析表中多少数据块

analyze table t2 compute statistics for table;
select table_name,blocks,num_rows from user_tables where table_name='T2';

然后再删除t2 数据表中3万行数据:

delete t2 where rownum < 30000;
commit;
analyze table t2 compute statistics for table;
select table_name,blocks,num_rows from user_tables where table_name='T2';

可以发现,数据行少了3万,但是占用的数据块却是没有变的。

用move对表的高水位线进行调整: 

alter table t2 move tablespace USERS;
analyze table t2 compute statistics for table;
select table_name,blocks,num_rows from user_tables where table_name='T2';

可以看出,T2表中的高水位线被刷新了。但是使用move之时,表不能有其他应用,同时表上的索引也要重新建立。

用Shrink语句收缩表,将数据行的数据块移动到另外一个数据块上,是数据收缩,收缩完后降低高水位线。收缩时可以DML操作(增删改),降低高水位线时不准DML操作。使用Shrink语句的前提是:表所在的表空间启用了ASSM自动段管理,表上也启用了ROW MOVEMENT

select s.TABLESPACE_NAME,s.SEGMENT_SPACE_MANAGEMENT from dba_tablespaces s
select table_name,u.ROW_MOVEMENT from user_tables u where table_name='T2';
alter table t2 enable row movement;
alter table t2 shrink space;
analyze table t2 compute statistics for table;
select table_name,blocks,num_rows from user_tables where table_name='T2';
---

truncate table [表名]:保留表结构删除所有表数据,无法回滚。这个操作也可以把HWM降到最低。

当数据量过多时,删除表结构的速度会非常慢:可以先把改列设成unused,再把unused 的列给删除,这样删除列的操作就会在数据库空闲的时候自动完成。

alter table [表名] set unused column [列名];      alter table t2 drop unused columns;

5.IOT表、簇表、临时表

IOT 索引组织表:这个表必须有主键,会自动地按照主键进行排序,是个有序的表。与普通表不同,普通表和表主键上的索引都会需要为它们留出存储空间,而IOT不存在主键的空间开销。索引(主键)是存放在一起的;数据存储在索引块中;所以经常通过主键来访问数据的话,IOT表更适合;

create table student_iot(
 sno int,
 sname varchar2(20),
 sage int , 
 constraints pk_student primary key(sno)
)
organization index    
pctthreshold 30 overflow tablespace users; --指定阈值30%,当一行记录太大超出了数据索引块的30%,其他列(sname 、sage)就会放到指定的表空间里users

删除索引表的溢出表,首先要先删除索引表,然后清空回收站,命令 : purge recyclebin;

簇表:两个相互关联的表数据,同时放到一个数据块中。这样关联查询时,就只有扫描1个数据块就行。

创建簇表步骤如下:簇的数据类型要和表字段的数据类型一致。

----1.创建簇-----
create cluster cluster1(ckey int);
----2.创建表时关联簇---------
create table student_cluster(
 sno int ,
 sname varchar2(20),
 sage int )
 cluster cluster1(sno);
----3.创建另一张表时关联簇---------
create table record_cluster(
 sno int ,
 record int )
 cluster cluster1(sno);
----4.簇上要建立索引-------
 create index index1 on cluster cluster1;


select * from user_clusters;  --查询簇的信息
 select * from user_clu_columns;  --查询簇的关联信息

----------5删除簇要先把簇表删除-----------
 drop table student_cluster;
 drop table record_cluster;
 drop cluster cluster1;

临时表:临时表的创建必定在临时表空间 TEMP,临时表数据只能在同一个session中看到,数据不被不同session所共享。每个session的临时表中的数据是完全独立的;

创建临时表语法如下:

create global temporary table student_temp(
 sno int ,
 sname varchar2(20),
 sage int ) 
 --on commit delete rows --(默认值);
 on commit preserve rows;

其中 on commit delete rows; 指明了当事物提交或回滚时,自动把临时表数据清除; on commit Preserve rows 指明了当Session 断开和数据库连接时才会删除临时表中的数据;

由图可以知道,两个Session 中的临时表是完全独立的,互不干扰,尽管用户都是相同的。指定 on commit preserve rows;的临时表 ,其中的数据不会因为commit而被清空。然而用户断开连接时,临时表中数据才会删除。

drop 掉临时表的前提是,所有使用这临时表的session中表内不准有数据。

当采用on commit delete rows创建临时表时,一提交数据,表中的数据就被清空

查询临时表信息:

 select u.TABLE_NAME as 表名,
 u.TEMPORARY as 是否是临时表,
 u.DURATION as 是否是事务型的建表方式
  from user_tables u  where  u.TABLE_NAME='STUDENT_TEMP';

猜你喜欢

转载自blog.csdn.net/superSmart_Dong/article/details/104504199
今日推荐