索引与表类似,也可以分区;
分区索引分为两类: •Locally partitioned index(局部分区索引) •Globally partitioned index(全局分区索引)
下面就来详细解析一下这两类索引。
一:Locally partitioned index(局部分区索引)
- 概念:
局部分区索引随表对索引完成相应的分区(即索引会使用与底层表相同的机制分区),每个表分区都有一个索引分区,并且只索引该表分区。
local_partitioned_index
如图,若一个表被划分为AB两个分区,则局部分区索引A就只索引A分区中的数据,局部分区索引B只索引B分区中的数据;
- 分类:
局部分区索引又分为两类: •Local prefixed index(局部前缀索引) •Local nonprefixed index(局部非前缀索引)
Ⅰ:局部前缀索引:以分区键作为索引定义的第一列
Ⅱ:局部非前缀索引:分区键没有作为索引定义的第一列
示例语句:
复制代码 create table local_index_example ( id number(2), name varchar2(50), sex varchar2(10) )
partition by range (id) ( partition part_1 values less than (5), partition part_2 values less than (10) )
--创建局部前缀索引;分区键(id)作为索引定义的第一列 create index local_prefixed_index on local_index_example (id, name) local;
--创建局部非前缀索引;分区键未作为索引定义的第一列 create index local_nonprefixed_index on local_index_example (name, id) local;
复制代码
注意:判断局部索引是前缀还是非前缀的只需要看分区键是否作为索引定义的第一列
- 什么时候该使用前缀索引?什么时候该使用非前缀索引?
对于该使用前缀还是非前缀索引,这完全取决于你的实际需求,你应该尽量从实际角度出发选择合适的索引方式以充分利用到其分区消除的特性。
如果查询首先访问索引的话,它能否实现分区消除完全取决于查询中使用的谓词(即Where筛选条件);
比如用上面的 local_index_example 表举例,现有两个查询:
①: select … from local_index_example where id = :id and name = :name;
②: select … from local_index_example where name = :name;
对于以上两个查询来说,如果查询第一步是走索引的话,则:
局部前缀索引 local_prefixed_index 只对 ① 有用;
局部非前缀索引 local_nonprefixed_index 则对 ① 和 ② 均有用;
如果你有多个类似 ① 和 ② 的查询的话,则可以考虑建立局部非前缀索引;如果平常多使用查询 ① 的话,则可以考虑建立局部前缀索引;
总之,重点是你要尽可能保证查询包含的谓词允许索引分区消除
-------------------延伸阅读:绑定变量(bind variable)--------------------
绑定变量是查询中的一个占位符,形如 :xxx 。
例如,要获取 emp 表中 empno 为 123 的记录,你可以执行如下两种查询:
①: select * from emp where empno = 123;
②: 先将绑定变量 :empno 的值设置为 123,再执行查询 select * from emp where empno = :empno;
第一种查询使用了 123 这样一个直接量(常量),如果有多个这样的查询的话,则每一个查询对数据库来说都是一个全新的查询,Oracle每次都会对查询进行解析、限定(命名解析)、安全性检查、优化等(简单地讲,就是每次执行时都要先编译); 第二种查询使用了 :empno 这样一个绑定变量,变量值在查询时动态指定,这个查询只会在第一次时编译,随后Oracle会把查询计划存储在一个共享池中方便以后重用,如此当以后再传入不同的 empno 值进行查询时,Oracle会直接调用第一次解析好的这个执行计划进行执行,这样查询效率将大幅提升
- 局部索引的唯一性
Oracle只保证索引分区内部的唯一性,跨分区的唯一性无法保证。
如果你想使用局部索引实现唯一性约束的话,则必须让分区键实现唯一性约束(UNIQUE 或 PRIMARY KEY)
二:Globally partitioned index(全局分区索引)
- 概念:
全局分区索引,顾名思义,就是针对整个表空间(全局)来说的。
在此,索引按范围(Range)或散列(Hash,Oracle 10g中引入)进行分区,一个分区索引(全局)可能指向任何(或全部的)表分区。
global_partitioned_index
对于全局分区索引来说,索引的实际分区数可能不同于表的分区数量;
全局索引的分区机制有别于底层表,例如表可以按 done_date 列划分为10个分区,表上的一个全局索引可以按 id 列划分为5个分区。
与局部索引不同,全局索引只有一类,即全局前缀索引(prefixed global index),索引分区键必须作为索引定义的第一列,否则执行会报错。
用例语句:
复制代码 --创建示例表,按id进行范围分区 create table global_index_example ( id number(2), name varchar2(50), age number(2) )
partition by range (id) ( partition part_1 values less than (5), partition part_2 values less than (10) )
--创建按age进行范围分区的全局分区索引 create index global_index on global_index_example(age) global
partition by range (age) ( partition index_part_1 values less than (20), partition index_part_2 values less than (maxvalue) )
复制代码
注意:
全局索引要求最高分区(即最后一个分区)必须有一个值为 maxvalue 的最大上限值,这样可以确保底层表的所有行都能放在这个索引中;
一般情况下,大多数分区操作(如删除一个旧分区)都会使全局索引无效,除非重建全局索引,否则无法使用
- 全局索引的使用:
1) 数据仓库
许多数据仓库系统都存在大量的数据出入,如典型的数据“滑入滑出”(即删除表中最旧的分区,并为新加载的数据增加一个新分区);
这个过程涉及: •去除老数据:最旧的分区要么被删除,要么与一个空表交换(将最旧的分区变为一个表),从而允许对旧数据进行归档; •加载新数据并建立索引:将新数据加载到一个“工作”表中,建立索引并进行验证; •关联新数据:一旦加载并处理了新数据,数据所在的表会与分区表中的一个空分区交换,将表中的这些新加载的数据变成分区表中的一个分区(分区表会变得更大)