针对网上sql优化验证

环境:oracle 11

1. IS NULL 与 IS NOT NUL

  不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。

  任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。
验证:

//表结构
create table TEST_BM
(
  deptno VARCHAR2(14)  Primary  not null,
  dname  VARCHAR2(14),
  loc    VARCHAR2(13)
)
//增加一个索引
create index TEST_BM_NAME on TEST_BM (DNAME);

//查询语句 验证is null
select * from TEST_BM a where a.dname is  null

DEFAULT NULL索引失效 sql is null 索引_DEFAULT NULL索引失效


从解释计划中可以看出来虽然dname有索引,但是还是走了全表扫描

//查询语句 验证is not null
select * from TEST_BM a where a.dname is not null

DEFAULT NULL索引失效 sql is null 索引_查询语句_02


从解释计划中可以看出来虽然dname有索引,但是还是走了全表扫描


2. 对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的

select * from TEST_BM a where a.dname||'U' ='22K9SbKb6lXhUU'

DEFAULT NULL索引失效 sql is null 索引_字段_03

从上图解释计划中,很明显的看到走的是全表扫描

3.带通配符(%)的like语句

select * from TEST_BM a where a.dname like '%2mDYhbiVY8hcP%'

DEFAULT NULL索引失效 sql is null 索引_查询语句_04


前后都有%的走的是全表扫描

select * from TEST_BM a where a.dname like '2mDYhbiVY8hcP%'

DEFAULT NULL索引失效 sql is null 索引_DEFAULT NULL索引失效_05


只是在后面有%走的是索引,但是也不一定,如果查询的结果很多,oracle会选择走全表扫描比如select * from TEST_BM a where a.dname like ‘2%’

DEFAULT NULL索引失效 sql is null 索引_查询语句_06


4.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
这个确实是这样的,但是这个东西只能说尽量避免。

5.应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描

select * from TEST_BM a where a.dname = '2mDYhbiVY8hcP' or a.loc='30ftf7IL6w0cx'

DEFAULT NULL索引失效 sql is null 索引_oracle_07


分析:因为loc没有索引,所以这条语句还是走了全表扫描。

可以改写成

select * from TEST_BM a where a.dname = '2mDYhbiVY8hcP' 
union all
select * from TEST_BM a where a.loc='30ftf1IL6w0cx'

这样上面的会走索引

6.in 和 not in 也要慎用,否则会导致全表扫描

select * from TEST_BM a where a.dname  in('2mDYhbiVY8hcP','21hz6uVXa4TTX','2aH5RPcQcsMdG','2aPpfZplfVTr2','2LUkuqXN9VKPg','2HgvKroBnvjkM')

DEFAULT NULL索引失效 sql is null 索引_oracle_08


可以看到in是会走索引的,而且oracle 内容把in翻译成or来处理

select * from TEST_BM a where a.dname not in('2mDYhbiVY8hcP','21hz6uVXa4TTX')

DEFAULT NULL索引失效 sql is null 索引_查询语句_09


not in是一定不走缩印的,not in在oracle内部处理方式 != <> 前面也讲到 慎用 != <>

7.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引

select * from TEST_BM a where substr(a.dname,0,2)='22'

DEFAULT NULL索引失效 sql is null 索引_oracle_10

//可以改写成
select * from TEST_BM a where a.dname like '22%'