达梦聚集索引

聚集索引

1.聚集索引简介

        表(列存储表和堆表除外)都是使用 B+树(以下简称 B 树)索引结构管理的,每一个普通表都有一个聚集索引,数据通过聚集索引键排序,根据聚集索引键可以快速查询任何记录。(即表是一个索引,这个索引名称叫聚集索引,可以理解为创建一个表后,将所有字段放在一起建立一个复合索引,只不过这个不需要我们来创建,系统自动给我们维护了一个)

        当建表语句未指定聚集索引键,DM 的默认聚集索引键是ROWID,即记录默认以 ROWID在页面中排序。ROWID 是 B 树为记录生成的逻辑递增序号,表上不同记录的 ROWID 是不一样的,并且最新插入的记录 ROWID 最大。很多情况下,以 ROWID 建的默认聚集索引并不能提高查询速度,因为实际情况下很少人根据 ROWID来查找数据。

验证默认聚集索引键是ROWID

2.数据准备

create table USERS (id number(12),name varchar2(20) not null,age int not null);

insert into USERS values(0001,'Tony',20);

insert into USERS values(0002,'Bill',21);

insert into USERS values(0003,'Jack',18);

insert into USERS values(0004,'Mark',20);

insert into USERS values(0005,'Lily',24);

insert into USERS values(0006,'Kobe',28);

insert into USERS values(0007,'James',29);

insert into USERS values(0008,'Henry',30);

insert into USERS values(0009,'Lisa',20);

insert into USERS values(0010,'Mila',18);

commit;

查询此表上的索引

select id,owner,name,index_type,table_name,table_type from SYSOBJECTS ob

join DBA_INDEXES idx

on ob.name=idx.index_name

where idx.owner='SYSDBA'

and idx.table_name='USERS';

        可以看到有生成了一个名为INDEX33555473的索引,索引类型是CLUSTER。

查看索引列:

select t1.owner,t1.index_name,t3.object_id,t1.index_type,t1.uniqueness,t2.table_name,t2.column_name from dba_indexes  t1

inner join user_ind_columns t2

on t1.index_name=t2.index_name

inner join dba_objects t3

on t1.index_name = t3.object_name

where t1.owner='SYSDBA';

查询结果为空,表示该索引不是表中的字段列,所以可以怀疑索引列是rowid。

查看该索引的定义,此索引在客户端中无法查看到。

select dbms_metadata.get_ddl(OBJECT_TYPE => 'INDEX',NAME=>upper('INDEX33555473'),SCHNAME => 'SYSDBA');

CREATE CLUSTER  INDEX "INDEX33555473" ON "SYSDBA"."USERS"( STORAGE(ON "MAIN", CLUSTERBTR) ;

可以看到,该索引的定义里面也没有指定索引列。

查询

select * from users where id=2;

从执行计划可以看到该查询走了聚集扫描(CLUSTER SCAN)。从这里也能看出来,INDEX33555473存储了USERS表的全部数据。

select rowid,* from users where rowid=2;

可以看到走的是聚集索引扫描(CLUSTER INDEX SEEK)。所以就可以验证聚集索引是以rowid为索引键的。

另外默认以rowid为索引键的聚集索引无法删除。

drop index INDEX33555473;

重建聚集索引后,该默认聚集索引则会自动删除。

create  cluster index idx_users_id on users(id);

select id,owner,name,index_type,table_name,table_type from SYSOBJECTS ob

join DBA_INDEXES idx

on ob.name=idx.index_name

where idx.owner='SYSDBA'

and idx.table_name='USERS';

可以看到默认的聚集索引已经不存在。

这时聚集索引是可以删除的,删除后原先的聚集索引会自动恢复。

drop index idx_users_id;

select id,owner,name,index_type,table_name,table_type from SYSOBJECTS ob

join DBA_INDEXES idx

on ob.name=idx.index_name

where idx.owner='SYSDBA'

and idx.table_name='USERS';

                  

但是聚集索引的名字变了,由原来的INDEX33555473变成了INDEX33555475。

DM 建表时提供三种方式供用户指定聚集索引键:

1

CLUSTER PRIMARY KEY

指定列为聚集索引键,并同时指定为主键,称为聚簇主键

2

CLUSTER KEY

指定列为聚集索引键,但是是非唯一的

3

CLUSTER UNIQUE KEY

指定列为聚集索引键,并且是唯一的

第一种方式受PK_WITH_CLUSTER参数影响,该参数为1才生效,参数功能如下:

3.PK_WITH_CLUSTER

PK_WITH_CLUSTER

1

动态,会话级

在建表语句中指定主关键字时,是否缺省指定为 CLUSTER,0:不指定;1:指定

注:该参数对列存储表和堆表无效

第一种方式在PK_WITH_CLUSTER=1时CLUSTER可以不写。如果指定CLUSTER关键字,无论PK_WITH_CLUSTER是0还是1都会创建聚集索引。

drop table USERS;

SP_SET_PARA_VALUE(1,'PK_WITH_CLUSTER',1);

create table USERS (

id number(12) primary key,

name varchar2(20) not null,

age int not null);

select t1.owner,t1.index_name,t3.object_id,t1.index_type,t1.uniqueness,t2.table_name,t2.column_name from dba_indexes  t1

inner join user_ind_columns t2

on t1.index_name=t2.index_name

inner join dba_objects t3

on t1.index_name = t3.object_name

where t1.owner='SYSDBA';

此时可以看到USERS表会有一个主键约束

--定义如下:

alter table "SYSDBA"."USERS" add constraint "CONS134218775" primary key("ID");

删除会报如下错误:

drop table USERS;

SP_SET_PARA_VALUE(1,'PK_WITH_CLUSTER',0);

create table USERS (

id number(12) primary key,

name varchar2(20) not null,

age int not null);

select t1.owner,t1.index_name,t3.object_id,t1.index_type,t1.uniqueness,t2.table_name,t2.column_name from dba_indexes  t1

inner join user_ind_columns t2

on t1.index_name=t2.index_name

inner join dba_objects t3

on t1.index_name = t3.object_name

where t1.owner='SYSDBA';

可以看到索引类型是NORMAL,不是CLUSTER。

select id,owner,name,index_type,table_name,table_type from SYSOBJECTS ob

join DBA_INDEXES idx

on ob.name=idx.index_name

where idx.owner='SYSDBA'

and idx.table_name='USERS';

可以看到有两个索引。

drop table USERS;

SP_SET_PARA_VALUE(1,'PK_WITH_CLUSTER',1);

create table USERS (

id number(12)  CLUSTER KEY,

name varchar2(20) not null,

age int not null);

select t1.owner,t1.index_name,t3.object_id,t1.index_type,t1.uniqueness,t2.table_name,t2.column_name from dba_indexes  t1

inner join user_ind_columns t2

on t1.index_name=t2.index_name

inner join dba_objects t3

on t1.index_name = t3.object_name

where t1.owner='SYSDBA';

可以看到NONUNIQUE。

drop table USERS;

SP_SET_PARA_VALUE(1,'PK_WITH_CLUSTER',1);

create table USERS (

id number(12)  CLUSTER UNIQUE KEY,

name varchar2(20) not null,

age int not null);

4.创建聚集索引的约束条件

1. 每张表中只允许有一个聚集索引,如果之前已经指定过 CLUSTER INDEX 或者指定了 CLUSTER PK,则用户新建立 CLUSTER INDEX 时系统会自动删除原先的聚集索引。但如果新建聚集索引时指定的创建方式(列,顺序)和之前的聚集索引一样,则会报错;

2. 指定 CLUSTER INDEX 操作需要重建表上的所有索引,包括 PK 索引;

3. 删除聚集索引时,缺省以 ROWID 排序,自动重建所有索引;

4. 若聚集索引是默认的 ROWID 索引,不允许删除

5. 聚集索引不能应用到函数索引中;

6. 不能在列存储表上新建/删除聚集索引;

7. 建聚集索引语句不能含有 partition_clause 子句;

8. 在临时表上增删索引会使当前会话上临时 b 树数据丢失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值