oracle 索引聚簇表的工作原理

作者:Richard-Lui

一:首先介绍一下索引聚簇表的工作原理:(先创建簇,再在簇里创建索引,创建表时指定列的簇类型

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

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

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

二:创建过程。

索引聚簇表是基于一个索引聚簇(index cluster)创建的。里面记录的是各个聚簇键。聚簇键和我们用得做多的索引键不一样,索引键指向的是一行数据,聚簇键指向的是一个ORACLE BLOCK。我们可以先通过以下命令创建一个索引簇。

SQL> conn scott/tiger

已连接。

SQL> desc dept

名称                                     是否为空? 类型

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

DEPTNONOT NULL NUMBER(2)

DNAMEVARCHAR2(14)

LOCVARCHAR2(13)

SQL> create cluster emp_dept_cluster

2 (deptno number(2) )

3 size1024

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 oncluster emp_dept_cluster

3 /

索引已创建。

现在可以创建表了:

SQL> conn segment_study/liugao

已连接。

SQL> create table dept

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

4 locvarchar2(13)

5 )

6 clusteremp_dept_cluster(deptno)

7 /

表已创建。

SQL> create table emp

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

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

10 )

11cluster emp_dept_cluster(deptno)

12 /

表已创建。

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

SQL> select cluster_name, table_name

2 fromuser_tables

3 wherecluster_name is not null

4 orderby 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 )

3loop

4 insertinto dept

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

6 insertinto emp

7 select*

8           from scott.emp9          where deptno = x.deptno;

10 endloop;

11end;

12 /

begin

*

第1行出现错误:

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

ORA-06512:在line 4

SQL> create index emp_dept_cluster_idx

2 oncluster 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可以查看此数据所在的BLOCKID,如果dept和emp存储的行数据不是一个BLOCK ID ,则标记一个‘*‘.查询结果如下:

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

3deptno

4 from(

5  selectdbms_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   whereemp.deptno = dept.deptno

10 )

11 orderby deptno

12 /

DEPT_BLKEMP_BLK F DEPTNO

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

85 86 *10

85 86 *10

85 87 *10

85 8520

85 87 *20

85 86 *20

85 8520

85 86 *20

85 8530

85 86 *30

85 8530

DEPT_BLKEMP_BLK F DEPTNO

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

85 86 *30

85 8530

85 8530

已选择14行。

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

时间: 2024-10-07 01:15:48

oracle 索引聚簇表的工作原理的相关文章

堆组织表,索引组织表和索引聚簇表

--- 堆组织表就不说了,其索引中记录了记录所在位置的rowid,查找的时候先找索引,然后再根据索引rowid找到块中的行数据 索引组织表,其行数据以索引形式存放,因此找到索引,就等于找到了行数据. -- 堆组织表的数据是散放的,索引和表的数据是分离的 索引组织表的索引和数据是在一起的 -- 堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录, 就必须得读取全部的记录以便筛选.而这个时候为了加快查询速度, 索引就出现了, 索引是针对少量特定字段的值拿出来进

[转帖]堆组织表,索引组织表和索引聚簇表

https://www.cnblogs.com/youngerger/p/8446399.html --- 堆组织表就不说了,其索引中记录了记录所在位置的rowid,查找的时候先找索引,然后再根据索引rowid找到块中的行数据 索引组织表,其行数据以索引形式存放,因此找到索引,就等于找到了行数据. -- 堆组织表的数据是散放的,索引和表的数据是分离的 索引组织表的索引和数据是在一起的 -- 堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录, 就必须得读取

Oracle索引聚簇因子的含义及重要性

索引统计信息中需要我们最为重点关注的是CLUSTERING_FACTOR(聚簇因子). 在Oracle数据库中,聚簇因子是指按照索引键值排序的索引行和存储于对应表中数据行的存储顺序和相似度.Oracle是按照如下的算法来计算聚簇因子的值: 聚簇因子的初始值为1. Oracle首先定位到目标索引处于最左边的叶子块. 从最左边的叶子块的第一个索引键值所在的索引行开始顺序扫描,在顺序扫描的过程中,Oracle会比对当前索引行的rowid和它之前的那个索引行(它们是相邻的关系)的rowid,如果这两个r

oracle聚簇表的理解 (转自:https://blog.csdn.net/gumengkai/article/details/51009345 )

Oracle支持两种类型的聚簇:索引聚簇和哈希聚簇 一.索引聚簇表的原理 聚簇:如果一些表有一些共同的列,则将这样一组表存储在相同的数据块中 聚簇还表示把相关的数据存储在同一个块上.利用聚簇,一个块可能包含多个表的数据. 概念上就是说如果两个表或多个表经常做连接操作,就可以预先把需要的数据也存储在一起. 聚簇还可以用于单个表,可以按某个列将数据分组存储. 简单的说,簇就是一组表,由一组共享相同数据块的多个表组成,将经常一起使用的表组合在一起成簇 就可以提高处理效率. 二.使用方法 建立的顺序:簇

Oracle索引总结(五)- Oracle索引种类之表簇索引(cluster index)

表簇索引(cluster index) 对于表簇索引而言,必须使用表簇. 由于簇索引与索引表簇关联紧密,无法单独拿出来总结,因此一并进行总结. 1.1 表簇的定义 表簇是一组通过相同公共列(簇键),构成的表的集合. 如上图,右侧独立的两张表,employees员工表与departments部门表,通过簇键department_id列,构成了左侧的一个表簇(cluster). 当构成表簇后,一个单独的数据块会包含多个表的数据行信息. 1.2 表簇的分类 对于oracle数据库,主要支持两种表簇:索

索引聚簇因子相关

create or replace function clustering_factor(p_owner in varchar2,p_table_name in varchar2,p_column_name in varchar2)return number isl_cursor sys_refcursor;l_clustering_factor binary_integer:=0;l_block_nr binary_integer:=0;l_previous_block_nr binary_i

Oracle索引大全

文档结构如下: 前言: Oracle 官方文档对索引的描述真是弱透了,对索引的说明就是一坨……,support也没有很好的资料,下面还是用的官方上的内容经过自己的整理加上网上的资料:至于为什么用索引,以及索引的重要性,相信大家都知晓:如果把数据库所有的表比如成一本书,那么,索引就是书的目录,你不可能每一次查看书的内容从第一页读到最后一页,不用目录吧!! 索引类型: 索引是与表和群集关联的可选结构,可以使SQL查询对表执行得更快.正如本手册中的索引可以帮助您更快地找到信息(没有索引)一样,Orac

filebeat工作原理

Filebeat是本地文件的日志数据采集器. 作为服务器上的代理安装,Filebeat监视日志目录或特定日志文件,tail file,并将它们转发给Elasticsearch或Logstash进行索引.kafka 等. 工作原理: Filebeat由两个主要组件组成:prospector 和harvester.这些组件一起工作来读取文件(tail file)并将事件数据发送到您指定的输出 启动Filebeat时,它会启动一个或多个查找器,查看您为日志文件指定的本地路径. 对于prospector

SQL索引工作原理

SQL 当一个新表被创建之时,系统将在磁盘中分配一段以8K为单位的连续空间,当字段的值从内存写入磁盘时,就在这一既定空间随机保存,当一个8K用完的时候, SQLS指针会自动分配一个8K的空间.这里,每个8K空间被称为一个数据页(Page),又名页面或数据页面,并分配从0-7的页号,每个文件的第0页记录引导信息,叫文件头(File header):每8个数据页(64K)的组合形成扩展区(Extent),称为扩展.全部数据页的组合形成堆(Heap). SQLS 规定行不能跨越数据页,所以,每行记录的