复合索引,不走索引情况
一般情况,查询中需要有复合索引的前导列,才会使用复合索引
3.1)INDEX SKIP SCAN(复合索引之索引跳跃扫描)
Oracle 9i后提供,有时候复合索引的前导列(索引包含的第一列)没有在查询语句中出现,oralce也会使用该复合索引,
这时候就使用的INDEX SKIP SCAN;
3.2)什么时候会触发 INDEX SKIP SCAN
前提条件:表有一个复合索引,且在查询时有除了前导列(索引中第一列)外的其他列作为条件,并且优化器模式为CBO时当Oracle发现前导列的唯一值个数很少时,会将每个唯一值都作为常规扫描的入口,在此基础上做一次查找,最后合并这些查询;
例如:
假设表emp有ename(雇员名称)、job(职位名)、sex(性别)三个字段,并且建立了如 create index idx_emp on
emp (sex, ename, job) 的复合索引;因为性别只有 '男' 和 '女'
两个值,所以为了提高索引的利用率,Oracle可将这个复合索引拆成 ('男', ename, job),('女', ename,
job)这两个复合索引;当查询 select * from emp where job = 'Programmer' 时该查询发出后:
Oracle先进入sex为'男'的入口,这时候使用到了 ('男', ename, job) 这条复合索引,查找 job =
'Programmer' 的条目;再进入sex为'女'的入口,这时候使用到了 ('女', ename, job) 这条复合索引,查找 job =
'Programmer' 的条目;最后合并查询到的来自两个入口的结果集。
不走索引的原因,大概有如下8种:
1)建立组合索引,但查询谓词并未使用组合索引的第一列,此处有一个INDEX SKIP SCAN概念。
2)在包含有null值的table列上建立索引,当时使用select count(*) from table时不会使用索引。
3)在索引列上使用函数时不会使用索引,如果一定要使用索引只能建立函数索引。
如:Where条件中对字段增加处理函数将不使用该列的索引
select * from emp where to_char(hire_date,'yyyymmdd')='20080411' (不使用)
select * from emp where hire_date = to_char('20080411','yyyymmdd') (使用)
4)当被索引的列进行隐式的类型转换时不会使用索引。
示例1:
select * from t where indexed_column = 5,而indexed_column列建立索引但类型是字符型,这时Oracle会产生隐式的类型转换,转换后的语句类似于select * from t where to_number(indexed_column) = 5,此时不走索引的情况类似于case3
示例2:日期转换也有类似问题
select * from t where trunc(date_col) = trunc(sysdate)其中date_col为索引列,这样写不会走索引,可改写成select * from t where date_col >= trunc(sysdate) and date_col < trunc(sysdate+1),此查询会走索引。
5)并不是所有情况使用索引都会加快查询速度,full scan table 有时会更快,尤其是当查询的数据量占整个表的比重较大时,因为full scan table采用的是多块读,
当Oracle优化器没有选择使用索引时不要立即强制使用,要充分证明使用索引确实查询更快时再使用强制索引。
6)<>
7)like’%dd’百分号在前
8)not in ,not exist