1 索引概述
如果要在表中查询指定记录,在没有索引时必须遍历整表,有索引时只要在索引中找到符合查询条件的索引字段值,就可以通过保存在索引中的ROWID快速找到表中对应的记录。
2 索引创建
CREATE UNIUQE | BITMAP INDEX <schema>.<index_name>
ON <schema>.<table_name>
(<column_name> | <expression> ASC | DESC,
<column_name> | <expression> ASC | DESC,...)
TABLESPACE <tablespace_name>
STORAGE <storage_settings>
LOGGING | NOLOGGING
COMPUTE STATISTICS
NOCOMPRESS | COMPRESS<nn>
NOSORT | REVERSE
PARTITION | GLOBAL PARTITION<partition_setting>
相关说明
1)UNIQUE | BITMAP:指定UNIQUE为唯一值索引,BITMAP为位图索引,省略为B-Tree索引。
2)<column_name> | <expression> ASC | DESC:可以对多列进行联合索引,当为expression时即“基于函数的索引”
3)TABLESPACE:指定存放索引的表空间(索引和原表不在一个表空间时效率更高)
4)STORAGE:可进一步设置表空间的存储参数
5)LOGGING | NOLOGGING:是否对索引产生重做日志(对大表尽量使用NOLOGGING来减少占用空间并提高效率)
6)COMPUTE STATISTICS:创建新索引时收集统计信息
7)NOCOMPRESS | COMPRESS<nn>:是否使用“键压缩”(使用键压缩可以删除一个键列中出现的重复值)
8)NOSORT | REVERSE:NOSORT表示与表中相同的顺序创建索引,REVERSE表示相反顺序存储索引值
9)PARTITION | NOPARTITION:可以在分区表和未分区表上对创建的索引进行分区
3 索引优点
1) 通过创建唯一索引,保证表中每行数据唯一性
2) 可以大大加快数据检索速度,这是索引最主要的作用
3) 可以加速表与表之间的连接,特别是在实现数据的参考完整性方面
4) 在使用分组和排序子句进行数据检索时,可以显著减少查询分组和排序的时间
5) 通过使用索引,可以在查询过程中,使用优化隐藏起,提高系统性能
4 索引缺点
1) 创建索引和维护索引需要耗费额外的时间与空间,且会随着数据量的增加而增加,聚簇索引,占用的空间会更大
2) 对表中的数据进行DML操作时,索引也需要动态的维护,索引越多,DML速度越慢,尤其会影响insert与delete的速度
5 什么时候使用索引
1) 索引应该建立在where 子句频繁引用的列上,如果在大表上频繁使用某列或者某几列作为条件执行索引操作,并且检索行数低于15%,则可以考虑在这些列上建立索引
2) 如果需要基于某些列执行排序操作,在这些列建立索引可以加快数据排序速度
3) 多表连接时使用的连接列,应该建立索引,主要是外键
4) 在经常需要搜索的列上,可以建立索引加快搜索速度
6 不应该建立索引的列
1) 查询中很少使用的列
2) 数据值很少的列
3) blob数据类型的列
4) 修改性能远远大于检索性能时,不能创建索引
7 索引限制
SQL中有很多情况不能使用索引(已经建立索引)
1) 使用不等于操作符时(<> !=)
下面的查询及时在empno 列有一个索引查询仍然会执行一次全表扫描
select empno, ename from emp where empno<>70001;
把上面的查询改一下,索引就可以生效了,这是因为改了之后,查询是基于规则的优化器而不再试基于代价的优化器。
select empno, ename from emp where empno>70001 or empno<70001;
通过把不等于符号改成or条件,索引就生效了。
2) 使用IS NULL或者 IS NOT NULL
使用IS NULL或者IS NOT NULL 会限制索引使用,因为NULL值没有被定义,在SQL语句中使用NULL会有很多麻烦,因此建议开发人员
在建表时,把需要索引的列设为NOT NULL。
3) 使用函数
如果是非基于函数的索引,在SQL语句的where 子句中对存在索引的列使用函数时,会使优化器忽略这些索引,下面查询就不会使用索引
select empno, ename, deptno from emp where substr(empno,2,4)=0001;
改成下面语句,索引可以将生效
select empno, ename, deptno from emp where empno=substr(70001,2,4);
4) 比较不匹配的数据类型
这是较难发现的性能问题。注意下面的查询例子,account_number 数据类型为varchar2
select bank_name,address,city,state,zip from banks where account_number = 990354;
此时即使account_number 有索引也无法生效,查询时会进行全表扫描
改成数据类型相同的查询,索引才会生效:
select bank_name, address, city, state, zip from banks where account_number = '990354';
特别注意:不匹配的数据类型之间比较会让oracle自动限制索引使用,即使查询分析执行计划也不能找出为什么做了一次全部扫描
8 查询索引
表级索引,查询每个表的索引信息
select table_owner, table_name, index_name, index_type
from user_indexes
order by table_owner, table_name;
列级索引,查询每个表每个列的索引信息
select table_name, index_name, column_name, column_position, column_length, char_length, descend
from user_ind_columns
where table_name not like 'BIN$'||'%'
order by table_name, column_name;
9 组合索引
当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在 Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、 ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个值,否则就不能使用这个索引键进行一次范围扫描。
特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!
10 ORACLE ROWID
通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复值或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。
11 选择性
使用USER_INDEXES视图,该视图中显示了一个distinct_keys列。比较一下唯一键的数量和表中的行数,就可以判断索引的选择性。选择性越高,索引返回的数据就越少。
12 群集因子(Clustering Factor)
Clustering Factor位于USER_INDEXES视图中。该列反映了数据相对于已建索引的列是否显得有序。如果Clustering Factor列的值接近于索引中的树叶块(leaf block)的数目,表中的数据就越有序。如果它的值接近于表中的行数,则表中的数据就不是很有序。
13 二元高度(Binary height)
索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B- level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中值的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类似于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。
14 快速全局扫描
从Oracle7.3后就可以使用快速全局扫描(Fast Full Scan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的 DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。
15 跳跃式扫描
从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。
16 索引分类
Oracle提供大量的索引选项,知道在给定的条件下使用哪个选项对于应用程序的性能非常重要,一个错误的选择可能引发死锁,并导致数据库性能急剧下降或者进程终止。如果做出正确的选择,则可以合理的使用资源,提高数据库性能。
索引分为:
B树(默认类型)
Bitmap
HASH
索引组织表索引
反向键索引
基于函数的索引
分区索引(本地与全局索引)
位图连接索引
1) B树索引
B树索引时Oracle最常用的索引类型,它是以B树结构组织并存放索引数据的,是一个典型的树结构,其包含的组件主要是:
叶子节点(Leaf node):包含条目直接指向表里的数据行。
分支节点(Branch node):包含的条目指向索引里其他的分支节点或者是叶子节点。
根节点(Root node):一个B树索引只有一个根节点,它实际就是位于树的最顶端的分支节点。
本文主要内容来自博客:http://blog.csdn.net/fengshuiyue/article/details/13172129