where 用到的字段没建立索引,就不走索引。 sql
下面这三种状况也会走索引。 编程
where field1 like '%abc%' --like %
where substr(field1,1)='a' --函数
where field1 in ('a','b','c') --in oracle
索引列有函数处理或隐式转换,不走索引 函数
索引列倾斜,个别值查询时,走索引代价比走全表扫描高,因此不走索引 优化
索引列没有限制 not null,索引不存储空值,若是不限制索引列是not null,oracle会认为索引列有可能存在空值,因此不会按照索引计算) spa
一、查询谓词没有使用索引的主要边界,可能会致使不走索引。好比,你查询的是SELECT * FROM T WHERE Y=XXX;假如你的T表上有一个包含Y值的组合索引,可是优化器会认为须要一行行的扫描会更有效,这个时候,优化器可能会选择TABLE ACCESS FULL,可是若是换成了SELECT Y FROM T WHERE Y = XXX,优化器会直接去索引中找到Y的值,由于从B树中就能够找到相应的值。 索引
二、若是在B树索引中有一个空值,那么查询诸如SELECT COUNT(*) FROM T 的时候,由于HASHSET中不能存储空值的,因此优化器不会走索引,有两种方式可让索引有效,一种是SELECT COUNT(*) FROM T WHERE XXX IS NOT NULL或者是不能为空。 get
三、若是在T表上有一个索引Y,可是你的查询语句是这样子SELECT * FROM T WHERE FUN(Y) = XXX。这个时候索引也不会被用到,由于你要查询的列中全部的行都须要被计算一遍,所以,若是要让这种sql语句的效率提升的话,在这个表上创建一个基于函数的索引,好比CREATE INDEX IDXFUNT ON T(FUN(Y));这种方式,等于Oracle会创建一个存储全部函数计算结果的值,再进行查询的时候就不须要进行计算了,由于不少函数存在不一样返回值,所以必须标明这个函数是有固定返回值的。 效率
四、索引不适用于隐式转换的状况,好比你的SELECT * FROM T WHERE Y = 5 在Y上面有一个索引,可是Y列是VARCHAR2的,那么Oracle会将上面的5进行一个隐式的转换,SELECT * FROM T WHERE TO_NUMBER(Y) = 5,这个时候也是有可能用不到索引的。 sql语句
五、在Oracle的初始化参数中,有一个参数是一次读取的数据块的数目,好比你的表只有几个数据块大小,并且能够被Oracle一次性抓取,那么就没有使用索引的必要了,由于抓取索引还须要去根据rowid从数据块中获取相应的元素值,所以在表特别小的状况下,索引没有用到是情理当中的事情。
六、很长时间没有作表分析,或者从新收集表状态信息了,在数据字典中,表的统计信息是不许确的,这个状况下,可能会使用错误的索引,这个效率可能也是比较低的。
在《Oracle专家编程》这本书中,有一个很是不错的例子,在本机实际作一下,能对索引有一个更深的印象,大体就是
CREATE TABLE FOO(USERNAME VARCHAR2(100) PRIMARY KEY,USERID VARCHAR2(100));
产生一堆数据,而后查询SQL
CREATE TABLE FOOBAK SELECT * FROM FOO ORDER BY USERID DESC;
而后给USERNAME加上主键索引,而后查询SQL
可以看到两个使用了USERNAME pk 的索引,产生了不一样的执行计划,这个实实在在的说明了表的物理结构实实在在的影响了执行计划。