容易引起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时,如果两者字符集不一样,则默认的转换方式是将数据编码从数据库字符集转换为国家字符集。
简单总结:
比较时,一般是字符型转换为数值型,字符型转换为日期型
算术运算时,一般把字符型转换为数值型,字符型转换为日期型
连接时(||),一般是把数值型转换为字符型,日期型转换为字符型
赋值、调用函数时,以定义的变量类型为准。
容易引起oracle索引失效的原因很多: 1、在索引列上使用函数。如SUBSTR,DECODE,INSTR等,对索引列进行运算.需要建立函数索引就可以解决了。 2、新建的表还没来得及生成统计信息,分析一下就好了 3、基于cost的成本分析,访问的表过小,使用全表扫描的消耗小于使用索引。 4、使用 5、单独的>、 6、like "%
1.mysql中 int 与 varchar 类型的
隐式
转换
:
一,如果表定义的是varchar字段,传入的是int型数字,则会发生
隐式
转换
二,表定义的是int字段,传入的是varchar数字字符串,不会发生
隐式
转换
,如果在与数字字符串比较大小并且数字字符串还超过int定义的长度(会以字符串类型比较'$')会
隐式
转换
三,
隐式
转换
会扫描全表,造成字段的
索引
的阻塞。
对于
oracle
数据库来说,在条件允许的
情况
下,
oracle
可以帮我们自动做数据类型的
转换
,但是
oracle
还是建议我们最好使用
转换
函数(to_char()、to_date()、to_number()等)做显示的
转换
下面这个例子简单的测试了,由于
oracle
自动执行
隐式
转换
,导致
索引
无法正确使用的例子
建表T,其中ID列是字符类型
scott@DB01> create table
昨天DBA发来邮件说有一个SQL引起CPU高负载。查看了一下SQL,根据时间条件查询,时间是有
索引
的,但是CPU会突然飙高。
SELECT * FROM (
SELECT t1.*,rownum as rn
FROM (
SELECT count(:"SYS_B_0") as COUNT ,T.USER_ID, T.USER_N
使用显示
转换
更方便理解sql语句
隐式
转换
可能会降低sql语句的性能(比如
隐式
转换
不会使用普通
索引
)
在不同的环境下,
隐式
转换
可能不会一直有效。比如datetime to varchar2的
转换
,依赖于参数NLS_DATE_FORMAT,这个参数在不同会话或者客户端都可能会不同。
Oracle
中对不同类型的处理具有显式类型
转换
(Explicit)和
隐式
类型
转换
(Implicit)两种方式,对于显式类型
转换
,我们是可控的,但是对于
隐式
类型
转换
,当然不建议使用,
因为很难控制,有不少缺点,但是我们很难避免
1. 创建测试表和
索引
create table tn (id number, name varchar2(1));
create index idx_tn on tn (id);
create index idx_tn on tn (name);
分别对NU
Oracle
索引
是一种用于加速数据库查询的数据结构。使用
Oracle
索引
可以快速定位需要查询的数据,提高查询效率。以下是
Oracle
索引
的使用方法:
1. 创建
索引
:在需要创建
索引
的表上创建
索引
,使用CREATE INDEX语句指定
索引
名称、
索引
列和排序方式等参数。
2. 查看
索引
:可以使用
Oracle
的系统视图(如USER_INDEXES、USER_IND_COLUMNS)来查看数据库中
已经
创建的
索引
。
3. 使用
索引
:在查询数据时,可以使用WHERE子句来指定需要检索的列,并且使用
索引
列作为查询条件,以便
Oracle
数据库使用
索引
来加速查询。
4.
索引
类型:
Oracle
支持多种不同类型的
索引
,如B-tree
索引
、位图
索引
、哈希
索引
等,可以根据不同的查询需求选择适合的
索引
类型。
5. 维护
索引
:当表中的数据发生变化时(如增删改查),
索引
也需要进行维护以保证查询的正确性和效率。可以使用
Oracle
提供的REBUILD、ALTER INDEX等语句来进行
索引
的重建和维护。
总之,合理使用
Oracle
索引
可以大大提高数据库查询的效率,加快数据检索速度。