我们日常的开发过程中,必然少不了的是数据库的查询操作,而当数据量到达一定程度的时候,查询速度也会成为我们系统的瓶颈之一,这里总结一下oracle的sql查询语句优化。
from优化
在oracle当中,from多个表的时候,oracle连接表和表之间的顺序是从右到左检索的,以最右边的表作为基础表驱动,先把基础表进行排序,再去从第二个表中去寻找符合条件的数据,假设A中有1万数据,B中有10万数据,现在查询A和B中id相等的数据
SQL1:select * from A a,B b where a.id=b.id;
按照oracle连接规则,先把B中的10万条数据排序,从第一条开始查找B中id相等的数据,由于B有十万数据,所以要进行10万次的查询,从能把数据查询出来。
而如果我们把A作为基础表的话就是:
SQL2:select * from B b,A a where a.id=b.id;
这时候明显在1万次的查询就可以把数据查询出来,有些人也许会说SQL2是从10万数据中查询一条,而SQL1的是从1万条数据中查询一条,在时间上SQL2没有优势,但是每次查询的io,连接都是很大的资源消耗。
所以,在查询的时候尽量把数据较少的数据放在最右边会让查询速度有所提升,同样的多表查询的时候,一般三表以上的查询的时候,应该把连接表放在最右边,也就是被其他表引用的表作为基表。
select语句优化
在查询的过程当中,我们很喜欢使用*来查询,而oracle会在解析sql的时候自动为*解析为数据字典,这个过程虽然所用的资源和时间不多,但是也是影响查询速度的一种,所以在查询的时候给出我们想要的数据字典也会是一种良好的习惯。
索引优化
数据库索引是数据库当中的一个数据库对象,它的主要目的就是加快数据检索,或者在搜索时加快找到对应的主健id。更加直观和直接一点的说法是索引就是一个表的目录,就好像书一样,要查看一些内容之前,都是想浏览目录,再去准确定位要查的具体内容。
索引作为一个数据库的对象,它是和表数据独立分开的
基本语法是:
create index 索引名称 on 表名称(建立索引的列,建立索引的列……)
可以多列一起。
在创建表的时候,如果指定了表的主健,那么oracle会自动创建一个主健的索引,用于查询,主健索引是唯一的,所以查询的速度也会非常的块。
在不考虑索引维护代价的情况下,我们认为创建了索引就可以提高我们的数据查询速度,但是就算是建立了索引,在某些不规范的情况下也是有可能让我们辛辛苦苦创建的索引白白浪费。下面我们看一下,数据库索引的使用需要注意的一些事情。
Order by使用索引
假设有一张员工表,
id | name | sex | age | marry | pro | userNo | dept |
主健 | 姓名 | 性别 | 年龄 | 婚姻状况 | 职称 | 员工号 | 部门 |
Not null | Not null | Not null | Null | Not null | Null | Not null | Null |
order by只在以下两种非常严格的情况下触发索引查询:
- order by中所有的列都包含在相同的索引当中(如果有多个列),且他们的顺序是一致的。
- order by中的所有列必须定义为非空。
例如 (给年龄,员工号添加符合索引)
select * from user order by age 因为年龄是可空的,索引不会被使用
select * from user order by userno 不会引用索引,索引当中的第一个列必须出现而且也要在第一才会出发索引。
不要改变索引列的类型
在oracle查询的过程当中,oracle会对一些数据进行简单的类型转换,例如年龄是number 类型,员工号是varchar类型(给两者各自添加索引)
select * from user where userno=123 走索引
实际上oracle会把语句转化为
select * from user where userno=to_char(123)
userno类型未改变
select * from user where age=’18’ 不走索引,语句会转化为
select * from user where to_char(age)=‘18’
age类型被改变。
所以在写查询语句的时候,为了避免oracle数据库隐式的类型转换,尽量显示的转换查询类型,而且注意要把条件转化成数据库的存储类型。
where子句的索引触发
1 尽量不要使用不等于(!=,<>), 查询就是查询我们想要的内容,索引的使用能加快查询什么存在表中,但是不能加快查询什么不存在于表中。
例如要查询年龄不是18岁的
select * from user where age!=18 这个语句是不走索引的,但是我们可以修改成 select * from user where age>18 and age<18 这个是走索引的,会比之前的语句效率高很多
2 不要对索引列进行数学运算,因为+-*/ 其实也是函数的一种
select * from user where age+1>18 这也是不走索引的,因为在oracle中,没有为age+1 创建索引,值给age创建了索引。
3 不适用is null 和is not null 在oracle数据库当中null值得使用会有很多的麻烦,因为null值并没有被定义,在我们默认创建的索引方法当中,null值并不会被加载到索引当中去,无论是单列索引或者是符合索引,出现的null值不会被加到索引当中,对应的当我们去查询null值得时候,当然也不会走索引了。
4 注意模糊查询like的用法,在模糊查询当中
select * from user where name like ‘%a%’ 全局扫描,不走索引
select * from user where name like ‘%a’ 全局扫描,不走索引
select * from user where name like ‘a%’ 走索引
在模糊查询的时候,匹配前置位没有模糊条件时,使用索引查询,这其实和我们查找英文字典的时候是一个意思的。
5 复合索引的使用
例如给user调价一个索引值
create index index_1 on user(sex,age,marry);
在查询的时候
select * from user where sex=’男’ and age=18 走索引
select * from user where sex=’男’ or age=18 不走索引
select * from user where age=18 不走索引
select * from user where sex=’男’
使用复合索引的时候,where子句中在索引的列中存在or 或是索引中第一个索引之后的列单独出现,都会引起全表扫描。
注意:
很多人误以为null值的出现会完全把一个索引无效话,其实并不是这样,null值会让你在使用order by或者是查询null值得时候无效化索引的作用,因为null值并不会被加到简历的索引当中去。