今天的工作中因一张表数据量在100W上下(后续数据量还会不断增加)欲优化查询速度,决定给表中添加索引。


oracle的索引分为5种:唯一索引,组合索引,反向键索引,位图索引,基于函数的索引


创建索引:CREATE [unique] INDEX index_name ON table (column)
 
 

   unique --唯一索引 
 
 
 

   index_name --索引名称 
 
 
 

   table --表名 
 
 
 

   column (列) 
 
 
 
删除索引:DROP INDEX [schema.]indexname



索引是什么?



索引可当作是一本书的目录,一个表中的某列加了索引相当于在一个小表中单独记录了此列的信息,在查询大表时根据这个”目录“记载的rowid可以很快的找到对应的数据。



那么什么时候该创建索引又该创建什么索引呢?



1、表数据量大的情况下 (只有个几百条数据的情况下加了索引也没有什么感觉)



2、插入修改删除不频繁的业务表(开头说了索引列是要跟小表有一个关联的,如果频繁的增删改,小表也要进行修改,所以dml的语句会降低效率)



3、经常要把哪几个字段拿来进行查询或者排序这个时候可以考虑建立索引(唯一性越强的字段越适合加索引比如主键)


4、数据重复多的话用位图索引(比如性别、科室、类别等)


这里使用复合索引要把选择性强的索引来放组合的前面,选择性强的就是可以大量筛除数据的字段 注:oracle自ORACLE 10g开始已经丢弃了RBO优化器,使用了CBO。所以在 Mysql 中组合查询要遵守的前导列查询在10g之后可不用遵守。即表test中有组合索引a,b,c,d 在Mysql中where条件中必须a字段放到第一位上,如果查询bcd,或者bacd都不会走索引。


6、这个时候我想到如果既有单字段索引,又有这几个字段上的复合索引,那直接建立一个大的复合索引就好了啊,实际情况却并不是想象的那么美好,在执行计划中,在有单字索引的时候,就不会走复合索引了,但是如果直接建立一个大的复合索引的话执行的效率却又没有选择性强的单字索引效率来的快,所以出现单字索引和复合索引有交叉的情况下一般删除复合索引(具体情况视业务来定)。

7、经常与其他表进行连接的表,在连接字段上应该建立索引。


为什么某些列查询时查看执行计划并没有走索引??


今天在一个时间列上加了索引在查看执行计划发现并没有走索引而是full的全表,百思不得其解,且使用了hint了以后效率也并没有增加多少。


创建nested索引 创建索引的两种途径_数据


后来发现到问题还是出在了先前说过的选择性上面,在查询时,如果回表数据大于表数据的15%(待考证)或者更多Oracle的优化器会自己选择full全表而不会通过索引查询,这个时候如果想使用索引需要使用hint。(但是优化结果可能达不到想要的结果)

在缩小了时间点后,减少了回表数据,果然又走了索引


创建nested索引 创建索引的两种途径_创建nested索引_02