oracle索引失效的情况已经oracle的一些隐式转换

来源:互联网 发布:游戏数据分析师 编辑:程序博客网 时间:2024/06/08 13:43

      容易引起oracle索引失效的原因很多:

      1、在索引列上使用函数。如SUBSTR,DECODE,INSTR等,对索引列进行运算.需要建立函数索引就可以解决了。

  2、新建的表还没来得及生成统计信息,分析一下就好了

  3、基于cost的成本分析,访问的表过小,使用全表扫描的消耗小于使用索引。

  4、使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,一般大于5%-15%就不走索引而走FTS。

  5、单独的>、<。

  6、like "%_" 百分号在前。

  7、单独引用复合索引里非第一位置的索引列。

  8、字符型字段为数字时在where条件里不添加引号。

  9、当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。

  10、索引失效,可以考虑重建索引,rebuild online。

  11、B-tree索引 is null不会走,is not null会走,位图索引 is null,is not null  都会走、联合索引 is not null 只要在建立的索引列(不分先后)都会走。

Oracle中对不同类型的处理具有显式类型转换(Explicit)和隐式类型转换(Implicit)两种方式,对于显式类型转换,我们是可控的,但是对于隐式类型转换,当然不建议使用,
因为很难控制,有不少缺点,但是我们很难避免碰到隐式类型转换,如果不了解隐式类型转换的规则,那么往往会改变我们SQL的执行计划,从而可能导致效率降低或其它问题。

在oracle中,如果不同的数据类型之间关联,如果不显式转换数据,则它会根据以下规则对数据进行隐式转换

 

1) 对于INSERT和UPDATE操作,oracle会把插入值或者更新值隐式转换为字段的数据类型。

   假如id列的数据类型为number

   update t set id='1'; -> 相当于 update t set id=to_number('1');

   insert into t(id) values('1') -> insert into t values(to_number('1'));

 

2) 对于SELECT语句,oracle会把字段的数据类型隐式转换为变量的数据类型。
   如假设id列的数据类型为varchar2

   select * from t where id=1; -> select * from t where to_number(id)=1;

   但如果id列的数据类型为number,则

   select * from t where id='1'; -> select * from t where id=to_number('1');(参考下文)

 

3) 当比较一个字符型和数值型的值时,oracle会把字符型的值隐式转换为数值型。

    如假设id列的数据类型为number

    select * from t where id='1'; -> select * from t where id=to_number('1');

 

4) 当比较字符型和日期型的数据时,oracle会把字符型转换为日期型。

    如假设create_date为字符型,

    select * from t where create_date>sysdate; -> select * from t where to_date(create_date)>sysdate;(注意,此时session的nls_date_format需要与字符串格式相符)

    假设create_date为date型,

    select * from t where create_date>'2006-11-11 11:11:11'; -> select * from t where   create_date>to_date('2006-11-11 11:11:11'); (注意,此时session的nls_date_format需要与字符串格式相符)

 

5) 如果调用函数或过程等时,如果输入参数的数据类型与函数或者过程定义的参数数据类型不一直,则oracle会把输入参数的数据类型转换为函数或者过程定义的数据类型。

   如假设过程如下定义 p(p_1 number)

   exec p('1'); -> exec p(to_number('1')); 6)

   赋值时,oracle会把等号右边的数据类型转换为左边的数据类型。

   如 var a number a:='1'; - > a:=to_number('1');

 

7) 用连接操作符(||)时,oracle会把非字符类型的数据转换为字符类型。

    select 1||'2' from dual; -> select to_char(1)||'2' from dual;

8) 如果字符类型的数据和非字符类型的数据(如number、date、rowid等)作算术运算,则oracle会将字符类型的数据转换为合适的数据类型,这些数据类型可能是number、date、rowid等。

    如果CHAR/VARCHAR2 和NCHAR/NVARCHAR2之间作算术运算,

    则oracle会将她们都转换为number类型的数据再做比较。

9) 比较CHAR/VARCHAR2 和NCHAR/NVARCHAR2时,如果两者字符集不一样,则默认的转换方式是将数据编码从数据库字符集转换为国家字符集。

 

简单总结:

比较时,一般是字符型转换为数值型,字符型转换为日期型

算术运算时,一般把字符型转换为数值型,字符型转换为日期型

连接时(||),一般是把数值型转换为字符型,日期型转换为字符型

赋值、调用函数时,以定义的变量类型为准。