`
xiang37
  • 浏览: 414272 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

[转]Oracle聚簇表

 
阅读更多

Oracle 支持两种类型的聚簇:索引聚簇和哈希聚簇

 

使用索引聚簇指南

一:首先介绍一下索引聚簇表的工作原理:

  聚簇如果一组表有一些共同的列,则将这样一组表存储在相同的数据库块中;聚簇还表示把相关的数据存储在同一个块上。利用聚簇,一个块可能包含多个表的数据。概念上就是如果两个或多个表经常做链接操作,那么可以把需要的数据预先存储在一起。聚簇还可以用于单个表,可以按某个列将数据分组存储。

  更加简单的说,比如说,EMP表和DEPT表,这两个表存储在不同的segment中,甚至有可能存储在不同的TABLESPACE中,因此,他们的数据一定不会在同一个BLOCK里。而我们有会经常对这两个表做关联查询,比如说:select * from emp,dept where emp.deptno = dept.deptno .仔细想想,查询主要是对BLOCK的操作,查询的BLOCK越多,系统IO就消耗越大。如果我把这两个表的数据聚集在少量的BLOCK里,查询效率一定会提高不少。

  比如我现在将值deptno=10的所有员工抽取出来,并且把对应的部门信息也存储在这个BLOCK里(如果存不下了,可以为原来的块串联另外的块)。这就是索引聚簇表的工作原理。

二:创建过程。

  索引聚簇表是基于一个索引聚簇(index cluster)创建的。里面记录的是各个聚簇键

聚簇键和我们用得做多的索引键不一样,索引键指向的是一行数据,聚簇键指向的是一个ORACLE BLOCK。我们可以先通过以下命令创建一个索引簇。

  SQL> conn scott/tiger

  已连接。

  SQL> desc dept

  名称 是否为空? 类型

  ----------------------------------------- -------- ----------------------------

  DEPTNO NOT NULL NUMBER(2)

  DNAME VARCHAR2(14)

  LOC VARCHAR2(13)

  SQL> create cluster emp_dept_cluster

  2 ( deptno number(2) )

  3 size 1024

  4 /

  簇已创建。

  这个名字可以用户定义,不一定叫deptno,数据类型必须和需要使用这个聚簇的数据类型一致NUMBER(2)。在这里最关键的一个参数是size。这个选项原来告诉Oracle:我们希望与每个聚簇键值关联大约1024字节的数据(1024对于一般的表一条数据没问题),Oracle会在用这个数据库块上设置来计算每个块最 多能放下多少个聚簇键。假设块大小为8KB,Oracle会在每个数据库块上放上最多7个聚簇键,也就是说,对应部门10、20、30、40、50、60和70的数据会放在一个块上,一旦插入部门80,就会使用一个新块。存放的数据是和插入顺序相关的。

  因 此,SIZE测试控制着每块上聚簇键的最大个数。这是对聚簇空间利用率影响最大的因素。如果把这个SIZE设置得太高,那么每个块上的键就会很少(单位BLOCK可以存的聚簇键就少了),我们会不必要地使用更多的空间。如果设置得太低,又会导致数据过分串链(一个聚簇键不够存放一条数据),这又与聚簇本来的目的不符,因为聚簇原本是为了把所有相关数据都存储在一个块上。

  向聚簇中放数据之前,需要先对聚簇建立索引。可以现在就在聚簇中创建表,但是由于我们想同时创建和填充表,而有数据之前必须有一个聚簇索引,所以我们先来建立聚簇索引。

  聚簇索引的任务是拿到一个聚簇键值,然后返回包含这个键的块的块地址。实际上这是一个主键,其中每个聚簇键值指向 聚簇本身中的一个块。因此,我们请求部门10的数据时,Oracle会读取聚簇键,确定相应的块地址,然后读取数据。聚簇键索引如下创建:

  SQL> create index emp_dept_cluster_idx

  2 on cluster emp_dept_cluster

  3 /

  索引已创建。

  现在可以创建表了:

  SQL> conn segment_study/liugao

  已连接。

  SQL> create table dept

  2 ( deptno number(2) primary key, 3 dname varchar2(14),

  4 loc varchar2(13)

  5 )

  6 cluster emp_dept_cluster(deptno)

  7 /

  表已创建。

  SQL> create table emp

  2 ( empno number primary key, 3 ename varchar2(10), 4 job varchar2(9), 5 mgr number, 6 hiredate date, 7 sal number, 8 comm number,

  9 deptno number(2) constraint emp_fk references dept(deptno)

  10 )

  11 cluster emp_dept_cluster(deptno)

  12 /

  表已创建。

  我们可以通过一下SQL语句查看创建:

  SQL> select cluster_name, table_name

  2 from user_tables

  3 where cluster_name is not null

  4 order by 1;

  CLUSTER_NAME TABLE_NAME

  ------------------------------ -----------------------------

  EMP_DEPT_CLUSTER DEPT

  EMP_DEPT_CLUSTER EMP

  现在,聚簇,聚簇索引,聚簇索引表都已经建立完成。

  三:加载数据。

  向聚簇索引表中加载数据是个很讲究的事情,处理方法不对,会使得聚簇的功能发挥不完全,降低查询性能。

  方法1:

  首先,我增加一个很大的列char(1000),加这个列是为了让EMP行远远大于现在的大小。使得一个1024的聚簇无法存储一行记录。不能加varchar2(1000),因为ORACLE对varchar2存储的原则是能省就省,如果数据数据不到1000,不会分配1000的空间的。char则是有多少用多少。呵呵。

  SQL> begin

  2 for x in ( select * from scott.dept )

  3 loop

  4 insert into dept

  5 values ( x.deptno, x.dname, x.loc );

  6 insert into emp

  7 select *

  8 from scott.emp 9 where deptno = x.deptno;

  10 end loop;

  11 end;

  12 /

  begin

  *

  第1行出现错误:

  ORA-02032:聚簇表无法在簇索引建立之前使用

  ORA-06512:在line 4

  SQL> create index emp_dept_cluster_idx

  2 on cluster emp_dept_cluster

  3 ;

  索引已创建。

  SQL> alter table emp disable constraint emp_fk;

  表已更改。

  SQL> truncate cluster emp_dept_cluster;

  簇已截断。

  SQL> alter table emp enable constraint emp_fk;

  表已更改。

  SQL> alter table emp add data char(1000);

  表已更改。

  上面的执行错误说明聚簇表无法在簇索引建立之前使用。

  首先我们通过先加载emp表,后加载dept表的方式。

  SQL> insert into dept

  2 select * from scott.dept;已创建4行。

  SQL> insert into emp

  2 select emp.*, '*' from scott.emp;已创建14行。

  然后做一个查询,通过dbms_rowid.rowid_block_number可以查看此数据所在的BLOCK ID,如果dept和emp存储的行数据不是一个BLOCK ID ,则标记一个'*'.查询结果如下:

  SQL> select dept_blk, emp_blk, 2 case when dept_blk <> emp_blk then '*' end flag,

  3 deptno

  4 from (

  5 select dbms_rowid.rowid_block_number(dept.rowid) dept_blk, 6 dbms_rowid.rowid_block_number(emp.rowid) emp_blk, 7 dept.deptno 8 from emp, dept 9 where emp.deptno = dept.deptno

  10 )

  11 order by deptno

  12 /

  DEPT_BLK EMP_BLK F DEPTNO

  ---------- ---------- - ----------

  85 86 * 10

  85 86 * 10

  85 87 * 10

  85 85 20

  85 87 * 20

  85 86 * 20

  85 85 20

  85 86 * 20

  85 85 30

  85 86 * 30

  85 85 30

  DEPT_BLK EMP_BLK F DEPTNO

  ---------- ---------- - ----------

  85 86 * 30

  85 85 30

  85 85 30

  已选择14行。

  我们发现,通过先插入emp数据,再插入dept数据,导致大部分的emp和dept的数据都不在一个block上,这不是我们使用聚簇索引的目的。

  方法二:

  先处理一下刚才插入的数据:

  SQL> truncate cluster emp_dept_cluster;

  truncate cluster emp_dept_cluster

  *

  第1行出现错误:

  ORA-02266:表中的唯一/主键被启用的外键引用

  SQL> alter table emp disable constraint emp_fk;

  表已更改。

  SQL> truncate cluster emp_dept_cluster;

  簇已截断。

  SQL> alter table emp enable constraint emp_fk;

  表已更改。

  然后使用以下的方式插入数据:

  SQL> begin

  2 for x in ( select * from scott.dept )

  3 loop

  4 insert into dept

  5 values ( x.deptno, x.dname, x.loc );

  6 insert into emp

  7 select emp.*, 'x' 8 from scott.emp 9 where deptno = x.deptno;

  10 end loop;

  11 end;

  12 /

  PL/SQL 过程已成功完成。

  执行上面统一的SQL。

  SQL> select dept_blk, emp_blk, 2 case when dept_blk <> emp_blk then '*' end flag,

  3 deptno

  4 from (

  5 select dbms_rowid.rowid_block_number(dept.rowid) dept_blk, 6 dbms_rowid.rowid_block_number(emp.rowid) emp_blk, 7 dept.deptno 8 from emp, dept 9 where emp.deptno = dept.deptno

  10 )

  11 order by deptno

  12 /

  DEPT_BLK EMP_BLK F DEPTNO

  ---------- ---------- - ----------

  85 85 10

  85 85 10

  85 85 10

  85 85 20

  85 85 20

  85 85 20

  85 86 * 20

  85 86 * 20

  86 86 30

  86 86 30

  86 86 30

  DEPT_BLK EMP_BLK F DEPTNO

  ---------- ---------- - ----------

  86 86 30

  86 87 * 30

  86 87 * 30

  已选择14行。

  咱们发现,大部分的数据都在同一个块中。原来这才是想聚簇表里添加数据的最佳方法。

  为什么会有这样的差别呢??

  当我们通过第一种方法时,有一个问题,由于dept表的行在聚簇中占用空间很小,但是剩余的空间确不能存一条dept的数据(应为我们添加了char(1000)了)。这样就会在那些聚簇 键块上导致过度的串链。Oracle会把包含这些信息的一组块串链或链接起来。如果同时加载对应一个给定聚簇键的所有数据,就能尽可能紧地塞满块,等空间 用完时再开始一个新块。 

 

四:什么时候不应该使用聚簇?

  1) 如果预料到聚簇中的表会大量修改:必须知道,索引聚簇会对DML的性能产生某种负面影响(特别是INSERT语句)。管理聚簇中的数据需要做更多的工作。

  2) 如果需要对聚簇中的表执行全表扫描:不只是必须对你的表中的数据执行全面扫描,还必须对(可能的)多个表中的数据进行全面扫描。由于需要扫描更多的数据,所以全表扫描耗时更久。

  3) 如果你认为需要频繁地TRUNCATE和加载表:聚簇中的表不能截除。这是显然的,因为聚簇在一个块上存储了多个表,必须删除聚簇表中的行。

  因此,如果数据主要用于读(这并不表示“从来不写”;聚簇表完全可以修改),而且要通过索引来读(可以是聚簇键索引,也可以是聚簇表上的其他索引),另外会频繁地把这些信息联结在一起,此时聚簇就很适合。

 

补充关于需要使用聚簇表的情况:

l 考虑对经常在连接语句中访问的表建立聚簇。

l 如果表只是偶尔被连接或者它们的公共列经常被修改,则不要聚簇表。(修改记录的聚簇键值比在非聚簇的表中修改此值要花费更多的时间,因为Oracle 必须将修改的记录移植到其他的块中以维护聚簇)。

 

l 如果经常需要在一个表上进行完全搜索,则不要聚簇这个表(对一个聚簇表进行完全搜索比在非聚簇表上进行完全搜索的时间长,Oracle 可能要读更多的块,因为表是被一起存储的。)

l 如果经常从一个父表和相应的子表中查询记录,则考虑给1 对多(1:* )关系创建聚簇表。(子表记录存储在与父表记录相同的数据块中,因此当检索它们时可以同时在内存中,因此需要Oracle 完成较少的I/O )。

l 如果经常查询同一个父表中的多个子记录,则考虑单独将子表聚簇。(这样提高了从相同的父表查询子表记录的性能,而且也没有降低对父表进行完全搜索的性能)。

l 如果从所有有相同聚簇键值的表查询的数据超过一个或两个Oracle 块,则不要聚簇表。(要访问在一个聚簇表中的记录,Oracle 读取所有包含那个记录值的全部数据块,如果记录占据了多个数据块,则访问一个记录需要读的次数比一个非聚簇的表中访问相同的记录读的次数要多)。

 

 

使用哈希聚簇指南

l 当经常使用有相同列的包含相等条件的查询子句访问表时,考虑使用哈希聚簇来存储表。使用这些列作为聚簇键。

l 如果可以确定存放具有给定聚簇键值的所有记录所需的空间(包括现在的和将来的),则将此表以哈希聚簇存储。

l 如果空间不够,并且不能为将要插入的新记录分配额外的空间,那么不要使用哈希聚簇。

l 如果偶尔创建一个新的、很大的哈希聚簇来保存这样的表是不切实际的,那么不要用哈希聚簇存储经常增长的表。

l 如果经常需要进行全表搜索,并且必须要为表的预期增长中的哈希聚簇分配足够的空间,则不要将此表以哈希聚簇存储。(这样的完全检索必须要读分配给哈希聚簇的全部块,即使有些块可能只包含很少的记录。单独地存储表将减少由完全的表检索读取的块的数量。)

l 如果你的应用程序经常修改聚簇键的值,则不要将表以哈希聚簇方式存储。

l 不管这个表是否经常与其他表连接,只要进行哈希对于基于以前的指南的表是合适的,那么在哈希聚簇中存储一个表可能是有用的。

 

http://blog.sina.com.cn/s/blog_6bd7d94301014kji.html

分享到:
评论

相关推荐

    Oracle中聚簇表的使用

    Oracle中聚簇表的使用,详细的介绍了oracle中聚簇表的创建及使用。

    Oracle中聚簇表Cluster Table使用图文详解

    大家通常oracle中的cluster的理解是不准确的,经常和sql server中的cluster index混淆。Cluster是存储一组table的一种方法,这些table共享同一数据块中的某些相同column,并把不同table在这一共享column上值相同的...

    高性能动态SQL Oracle数据安全 Oracle 数据库的聚簇技术 等等

    Oracle 数据库的聚簇技术 61 数据库、服务名、实例 63 Oracle内存结构 64 sys用户和system用户 67 Oracle SQL语句 67 GROUPING SETS分组 74 Oracle外部程序触发 75 Oracle数据库的备份与恢复 77 Oracle分区功能提高...

    数据库中聚簇索引与非聚簇索引的区别[图文]

    正式因为如此,所以一个表最多只能有一个聚簇索引。 不过这个定义太抽象了。在SQL Server中,索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然...

    Oracle表的分类以及相关参数的详解

    oracle中有如下几种类型的表:1、堆组织表(heap organized tables):常用的表类型,以堆的方式管理,当增加数据时,将使用段中第一个适合数据大小的...4、散列聚簇表:和聚簇表相似,但是不是用B*Tree索引聚簇码定位数

    Oracle数据库恢复工具Oracle Database Unloader(ODU)3.09

    支持各种表,普通的HEAP表,IOT表,聚簇(CLUSTER)表。 DESC表,以显示表的列定义 支持10g及以上的大文件(BigFile)表空间 列出表的分区和子分区 支持表被truncate后的数据恢复 支持表被drop后的数据恢复 支持...

    Oracle Index 索引介绍

    NULL 博文链接:https://dolphin-ygj.iteye.com/blog/444147

    Oracle四大宝典之四:Oracle 调优入门到精通

    你所管理的Oracle系统性能是否“极好”,你的回答可能是“否”。你的系统在正常运行的情况下是否能降低资源的消耗?...第12章 聚簇 第13章 索引组织表 第14章 重要的ORACLE特性 第15章 分区 第16章 实体化视图

    oracle数据库修复

    支持各种表,包括普通的HEAP表,IOT表和聚簇(CLUSTER)表 支持IOT表: 支持普通IOT表的导出 支持压缩IOT表的导出 支持IOT表溢出段 支持IOT表分区(包括子分区) 只能在有SYSTEM表空间时才能导出IOT表 支持...

    赤兔Oracle数据库恢复软件 v11.6.zip

    12.能够恢复Oracle 11g及以上版本的SecureFile LOB(目前不支持压缩、去重和加密的SecureFile LOB)支持各种表,包括普通的HEAP表,IOT表和聚簇(CLUSTER)表 13.支持IOT表: 14.支持普通IOT表的导出 15.支持压缩...

    达内总结的java最新笔试题core java,sql,web应有尽有

    索引聚簇表:索引聚簇表是表相关的表共享同一数据块中的相同列,并把相关数据存储中同一个数据块上。创建索引聚簇表中最重要的是对SIZE参数有很好的估量,否则聚簇将会降低空间利用,降低效率。 使用索引聚簇表的...

    Oracle 9i数据库应用技术 电子教程

    12个PPT详细讲解Oracle ...第6章 Oracle 索引与聚簇 第7章 Oracle 视图 第8章 Oracle 的其它对象 第9章 Oracle 数据查询 第10章 Oracle 编程接口 第11章 Oracle 安全管理 第12章 Oracle 数据库备份和恢复

    oracle 其他数据库对象

    5.1 数据库模式对象 5.2 索引 5.3 序列 5.4 同义词 5.5 聚簇 5.6 数据库链接 5.7 练习

    Oracle常用知识点小合集

    11g导出至10g、密码有效期问题、数据导出不完整、JOB不执行、创建大文件表空间、更改字符集、CPU使用情况、聚簇索引、通过dblink获取lob字段、无法识别本地sid、修复SPFILE文件、序列跳号问题、中文转拼音、自动备份...

    Oracle 9i&10g编程艺术:深入数据库体系结构(全本)含脚本

    10.7 有序散列聚簇表 386 10.8 嵌套表 390 10.8.1 嵌套表语法 390 10.8.2 嵌套表存储 399 10.8.3 嵌套表小结 402 10.9 临时表 402 10.10 对象表 410 10.11 小结 418 第11章 索引 421 11.1 Oracle索引概述 ...

    oracle 2 基本对象(索引,约束)2

    [2]oracle 2 基本对象(索引,约束) 表(Table)和 视图(View) 索引(Index)和 约束(Constraint) 函数(Function) 过程(Procedure) 其他(同义词,序列,簇,job,等)

    《Oracle DBA手记——数据库诊断案例与性能优化实践》第一章 to be continued

    ├─第一篇 DBA工作手记 │ 01.Eygle的DBA工作手记 │ 02.Yangtingkun的DBA工作手记 │ 03.老熊的DBA手记 │ 04.BanPing的DBA工作...聚簇因子、柱状图与执行计划 04.表碎片及分页查询优化 05.一次排序的调整与优化

    Oracle_Concepts_中文版.pdf

    oracle 入门很不错的一个手册,对于开发者帮助很...• 你要使用的模式对象(表、索引、聚簇等); • 内置数据类型和用户定义的数据类型; • SQL存储过程; • 事务如何工作; • 优化器; • 数据完整性; • 并发控制

    PRM-DUL Oracle(数据库恢复工具) v4.1.zip

    》》支持各种表,包括普通的HEAP表和聚簇(CLUSTER)表数据恢复 》》支持表被truncate后的数据恢复 》》支持表被drop后的数据恢复 》》支持在没有SYSTEM表空间和数据字典损坏的情况下的非字典模式数据恢复,并能...

    Oracle编程艺术

    勘误表....................................................................................... 29 配置环境....................................................................................... 30 建立...

Global site tag (gtag.js) - Google Analytics