索引应用的技巧与注意事项
1、索引不要与表存放在同一个表空间内;
2、一个表的索引不要过多;
3、对于大表而且使用频繁的表,在生产时最好不要去加索引;
如果对大表进行索引,取出的数据大于总量的5%至10%,使用索引扫描会效率下降很多。如果通过索引,取出数据量为总量的50%以上,这个时候还不如全表扫描来得快。
4、数据量小的表,使用不频繁的不要单独另建立索引;
5、在查询条件中几个条件一起使用的,适合建立组合索引,否则不要建立组合索引,当单独引用非第一字段时将发生全表扫描;
在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引
6、在查询的时候,where条件不要对索引的列做处理,而要对后面的条件字段做处理。否则用不上这个列上的索引。
如: score_date 是varchar2类型,该列上有索引。
select
……
where trim(replace(s.SCORE_DATE, ‘-‘, ”)) <= ‘20071201’
……
上面这条sql用不上score_date列上的索引。
下面这条sql就能用上索引。
select
……
where SCORE_DATE <= ‘20071201’
……
如果不是基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。
下面的查询不会使用索引(只要它不是基于函数的索引)
select docterno,docterame,doctertno
from docter
where trunc(hiredate)=’01-MAY-81’;
把上面的语句改成下面的语句,这样就可以通过索引进行查找。
select docterno,doctername,docterno
from docter
where hiredate<(to_date(‘01-MAY-81’)+0.9999);
6.1: 表的某个字段是字符型的, 那么传入数字值不加引号的话,sql不走索引:
例子:
docset表的todocid字段新建了索引,但是这个sql就是不走索引,加hint也没有用.
select /+INDEX(docset IX_DOCSET_TODOCID)/ *
from docset
WHERE REPLYSENDFLAG = 1
and TODOCID in (141429, 141441);
执行计划如下:
SELECT STATEMENT, GOAL = ALL_ROWS Cost=1592 Cardinality=2 Bytes=650
TABLE ACCESS FULL Object wner=SEALDATA Object name=DOCSET Cost=1592 Cardinality=2 Bytes=650
后来发现, todocid这个字段是VARCHAR2(20)类型的, 不是number, 所以传入的值是数字的时候,要加引号,才能走索引, 否则要使用函数索引才能有效.
select /+INDEX(docset IX_DOCSET_TODOCID)/ *
from docset
WHERE REPLYSENDFLAG = 1
and TODOCID in (‘141429’, ‘141441’);
执行计划如下:
SELECT STATEMENT, GOAL = ALL_ROWS Cost=1 Cardinality=2 Bytes=650
INLIST ITERATOR
TABLE ACCESS BY INDEX ROWID Object wner=SEALDATA Object name=DOCSET Cost=1 Cardinality=2 Bytes=650
INDEX RANGE SCAN Object wner=SEALDATA Object name=IX_DOCSET_TODOCID Cost=1 Cardinality=2
7.一些SQL的写法会限制索引的使用:1.where子句中如果使用in、or、like、!= <>,均会导致索引不能正常使用,将”<>”换成”>and<”;将”is not null “换成”>=chr(0)”;2.使用函数时,该列就不能使用索引。3.比较不匹配数据类型时,该索引将会被忽略
一些SQL语句优化的写法:1.如果from是双表的查询时,大表放在前面,小表放在后面(基础表)。最后面的表是基础表。(只在基于规则的优化器中有效)2.如果三表查询时,选择交叉表(intersection table)作为基础表.(只在基于规则的优化器中有效)3.写where条件时,有索引字段的判断在前,其它字段的判断在后;如果where条件中用到复合索引,按照索引列在复合索引中出现的顺序来依次写where条件;4.查询数量较大时,使用表连接代替IN,EXISTS,NOT IN,NOT EXISTS等。5.ORACLE采用自下而上的顺序解析WHERE子句,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾
关于索引的使用要注意几个事项 :
1 首先数据量小的表不需要建立索引,因为小的表即使建立索引也不会有大的用处,还会增加额外的索引开销
2 不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义
3 经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率
4 索引并不是一劳永逸的,用的时间长了需要进行整理或者重建
5索引在数据库中是以表的形式存储的,太多的索引一定是增加开销的,还有,前面说的,索引在数据库中是以表的形式存储的,频繁更新(插入)的的字段不要建立索引,因为在字段中做更新(插入)操作后,索引也会更新的,这样的话效率会大大降低。
6索引当然不是越多越好,够用就是最好,如果建立过多的索引,那你保存的速度就会下降,如果你的数据库写特别频繁,那就需要注意了。