CREATE [bitmap|unique] INDEX index_name ON TABLE( column [, column]...) [reversed]
当从表中访问数据时,Oracle提供了两个选择:全表扫描或者从ROWID中读取一行。在加上索引的列进行查找时,Oracle首先在索引中查找,而索引是按顺序存储的,相应的索引项向Oracle提供了该项记录在磁盘中的确切位置。
索引改进性能的程度取决与数据的选择性以及在表的块之间分布数据的方式。如果数据非常具有选择性,即数据变化程度较大,则只有少数的行匹配索引值,Oracle能够快速查询匹配索引值的ROWID的索引,并快速查询少量相关表块。否则所以可能返回很多ROWID,降低查询的性能。可以查询USER_INDEXES视图的Distinct_Keys列来研究分析的成果,比较一下唯一键的行数(USER_INDEXES的Num_Rows列)。
如果数据非常具有选择性,但是相关行在表中的存储位置并不互相靠近,则会进一步减少索引的益处。当数据分散在表的多个块中时,最好不使用索引而是进行全表扫描。因为执行全表扫描时,Oracle使用多块读取以快速扫描表,基于索引的读取是单块读取,因此在使用索引时的目标是减少解决查询所需的单个块的数量。
索引通常能提高查询的性能,包括SELECT语句,UPDATE和DELETE命令的WHERE子句。一般来说索引会降低INSERT语句的性能,因为要同时对表和索引进行操作,还有大量行的DELETE操作。
唯一性
如果每个表中行的所有列都进依赖于主键,那么就认为这组表符合第三范式,因此主键的唯一性就十分重要,通过唯一索引能够保证键的唯一性。
如果试图在已有数据的表上创建唯一索引,若有数据重复则该命令将失败。向已创建唯一索引的表中插入或更新产生重复键的数据都会失败。
创建索引的时机
- 索引在大型表,在那些可能在where子句中以两边相等的形式出现在的列上时是非常有效的。
- 当查询的某个条件只返回很少的行,一般在整张表行数的5%以下时,索引会比较有效。
组合索引
当某个索引包含多个已索引的列时,我们称这个索引为组合索引。一般来说,组合索引的第一列应该是最有可能在WHERE语句中出现的列名,依此类推。跳跃式扫描使得WHERE子句只包含组合索引中的部分列时也能够通过该索引增强查询性能。
限制索引
限制索引是一些没有开发经验的开发人员经常犯的错误,在SQL中经常有一些陷阱会使一些索引无法使用:
- 使用不等运算符(<>、!=)
- 使用IS NULL 或IS NOT NULL
- 使用函数
- 比较不匹配的数据类型
索引的类型
- B树索引:B树索引在Oracle中是一个通用索引,是默认索引类型,用索引列的值的集合构造一棵二叉树,树叶块上存有相应的ROWID。
- 位图索引:位图索引不适合用于事务处理应用程序访问的表,他们最好被用于具有较少不同值数量的列,比如性别。当有多个可用的位图索引时,查询效率较高。
- HASH索引:必须要使用HASH集群,建立集群的同时建立存储表,所有与这个集群键相关的行都被存储在一个数据库块上。如果将HASH索引作为WHERE子句中的确切匹配,Oracle就可以通过一个HASH函数和I/O来访问数据——相比较之下B树索引的二元高度决定了I/O的数量。HASH索引可能是访问数据最快的方法,但其缺点也很明显,集群键上不同值的数目在创建集群之前就要知道,低估该值会会造成集群冲突,严重消耗资源,占用I/O。修改的方法只有重建集群,ALTER CLUSTER不能修改HASH键的数目。对于一个经常进行全表扫描的集群表,HASH集群可能会引起额外的资源消耗。因此,HASH对于一些包含有序值的静态数据非常有效。
- 索引组织表:将表的存储结构改成B树结构,以表的主键进行排序,由于行在物理上有序,对于一些涉及精确匹配与范围搜索的语句,索引组织表提供了一种基于键的快速访问机制,基于主键的UPDATE和DELETE语句性能也得到提高。如果不是经常在主键上进行查询,需要在其他列上创建二级索引。
- 反转键索引:在数据载入期间,部分索引和磁盘肯定比其他部分使用频繁得多。为了解决这个问题,可以把索引表空间存放在能够把文件物理分割在多个磁盘上的磁盘体系结构上,反转键索引存储使这些数据的值与原先存储的数值相反:1234、1235、1236被存成4321、5321、6321.需要注意的是不能对位图索引和索引组织表进行反转键处理。
- 函数索引:创建针对某一函数或表达式的索引。
- 分区索引:通过把一个索引分成多个片段,可以更快地访问。B树和位图索引可以被分区。
参考文献:
《Oracle Database 10g 性能调整与优化》
《Oracle Database 10g 完全参考手册》