1.簇表的概述
簇表(cluster)是一种可选的存储数据的方式。簇表由一组相同的列而且经常被一起使用的数据表构成,这组表在存储时会共享一部分的Data Blocks,例如有两张表employees ,departments,它们都包含department_id 这个列。当用户将这两个表组合成一个簇表时,Oracle在物理上将两张表各行的department_id 这个字段存储在一个Data Blocks上。下面的图显示了employees 和departments是如何存储的:
2.簇键:
* 簇键是列或多列的组合,为簇表所共有
* 在创建簇时指定簇键的列,以后在创建增加的簇中的每个表时,指定相同的列即可
* 每个簇键值在簇和簇索引中仅仅存储一次,与不同表中有有多少这样的行无关
3.使用簇表的优点:
* 减少磁盘I/O,降低因使用联合查询所带来的系统开销。
* 节省了磁盘存储空间,可以将多张表的共享字段只存储一份。
4.何时创建簇表:
* 经常使用查询,DML操作较少的表
* 经常使用联合查询的表。
5.创建簇表的步骤:
* 创建簇
* 创建簇索引
* 创建簇表
6.创建簇、簇键、簇表时考虑的问题
* 哪些表适用于创建簇
* 对于创建簇的表哪些列用作簇列
* 创建簇时数据块空间如何使用(pctfree,pctused)
* 平均簇键及相关行所需的空间大小
* 簇索引的位置(比如存放到不同的表空间)
* 预估簇的大小
7.创建簇
SQL> create cluster emp_dept_cluster(department_id number(2))
2 pctused 80
3 pctfree 10
4 size 1024
5 tablespace users;
Cluster created
在上面创建的簇中一个最重要的参数就是size,需要为size 指定合适的大小,如果size 指定的太大,则每个块仅仅能存放少量的簇,容易引起空间的浪费,如果指定的太小,则容易产生过多的数据链,pctused是指当块里的数据低于多少百分比时,有可以重新被insert,一般默认是40%,即:当块里的数据低于40%的时候,又可以重新写入数据,这时候处于下降期。pctfree是指当块里的剩余空间少于多少百分比的时候,不允许被insert,只能被用于update,即:当block的剩余空间多余pctfree之前,是可以一直insert数据的,这时候出于上升期。
8.创建簇索引的条件:
* 模式中必须包含簇
* 必须拥有create any index的权限
9.簇索引的作用:用于一个簇键值并返回包含该簇键值的地址块。
10.创建簇索引:
SQL> create index emp_dept_cluster_index on cluster emp_dept_cluster;
Index created
注意:如果没有簇索引无法向簇表插入数据。
11.创建簇表
SQL> create table emp
2 (department_id number(2) primary key,
3 ename varchar2(15),
4 job varchar2(10)
5 )
6 cluster emp_dept_cluster(department_id);
Table created
SQL> create table dept
2 (department_id number(2) primary key,
3 dname varchar2(14),
4 loc varchar2(13)
5 )
6 cluster emp_dept_cluster(department_id);
Table created
对于创建的簇表,与普通表的唯一差别是使用了cluster关键字,即告诉oracle 基表的哪一列将映射到簇表中
查看我们刚刚创建的对象:
SQL> select t.object_name,t.object_type,t.status from user_objects t order by t.created desc;
OBJECT_NAME OBJECT_TYPE STATUS
DEPT TABLE VALID –簇表
SYS_C004683 INDEX VALID
EMP TABLE VALID –簇表
SYS_C004682 INDEX VALID
EMP_DEPT_CLUSTER_INDEX INDEX VALID –簇索引
EMP_DEPT_CLUSTER CLUSTER VALID –簇
12.更改簇
对于已经创建的簇,我们可以修改簇的相关属性,比如
修改簇的物理属性(pctfree,pctused,initrans,maxtrans等)
存储簇键值的所有行所需空间的平均值(size)
默认的并行度
alter cluster emp_dpet_cluster
pctfree 20
initrans 3;
13.删除簇
删除簇的同时会连同簇表,簇索引一起删除。
SQL> drop cluster emp_dept_cluster including tables;
Cluster dropped
SQL> select * from emp;
select * from emp
ORA-00942: 表或视图不存在
SQL> select * from dept;
select * from dept
ORA-00942: 表或视图不存在
SQL> drop index emp_detp_cluster_index;
drop index emp_detp_cluster_index
ORA-01418: 指定的索引不存在
14.簇相关的视图
dba_clusters
all_clusters
user_clusters
dba_clu_columns
user_clu_columns
15.演示相关操作
查看dba_clusters视图获得所创建的簇
SQL> select cluster_name,tablespace_name,pct_free,pct_used,ini_trans
2 from dba_clusters where owner = ‘ROBINSON’;
CLUSTER_NAME TABLESPACE_NAME PCT_FREE PCT_USED INI_TRANS
-------------------- ------------------------------ ---------- ---------- ----------
EMP_DEPT_CLUSTER USERS 15 2
查看簇列
SQL> select * from user_clu_columns;
CLUSTER_NAME CLU_COLUMN_NAME TABLE_NAME TAB_COLUMN_NAME
-------------------- -------------------- -------------------- ----------------------------------------
EMP_DEPT_CLUSTER DEPTNO DEPT DEPTNO
EMP_DEPT_CLUSTER DEPTNO EMP DEPTNO
修改簇的相关属性
SQL> alter cluster emp_dept_cluster
2 pctfree 20
3 initrans 3;
Cluster altered.
SQL> select cluster_name,tablespace_name,pct_free,pct_used,ini_trans
2 from dba_clusters where owner = 'JAX';
CLUSTER_NAME TABLESPACE_NAME PCT_FREE PCT_USED INI_TRANS
-------------------- ------------------------------ ---------- ---------- ----------
EMP_DEPT_CLUSTER USERS 20 3
从dba_segments可以看到簇产生了簇段,簇索引产生的为索引段
SQL> select segment_name,tablespace_name,segment_type from dba_segments where owner = 'ROBINSON';
SEGMENT_NAME TABLESPACE_NAME SEGMENT_TYPE
-------------------- ------------------------------ ------------------
EMP_DEPT_CLUSTER USERS CLUSTER
EMP_DEPT_CLUSTER_IDX USERS INDEX
SYS_C005422 USERS INDEX
SYS_C005423 USERS INDEX
删除簇,簇为非空时收到错误提示
SQL> drop cluster emp_dept_cluster;
drop cluster emp_dept_cluster
*
ERROR at line 1:
ORA-00951: cluster not empty
使用including tables 删除簇及簇表、簇索引
SQL> drop cluster emp_dept_cluster including tables;
Cluster dropped.
SQL> select segment_name,tablespace_name from dba_segments where owner = 'ROBINSON';
no rows selected