系统优化中很重要的方面是SQL语句的优化,对于海量数据,优质的SQL能够有效的提高系统的可用性。
总结的有点罗嗦,列个简单的目录啦~
目录
第一部分知识准备 第二部分常用sql用法和注意事项
第三部分 sql优化总结
1. sql执行过程 1.
exists 和 in 1. 优化一般原则
2. sql 共享 2.
union 和 union all 2. 具体注意事项
3. 绑定变量 3.
with as
4. 数据表访问方式 4.
order by
5. sql 执行顺序 5.
group by
6. 索引使用 6.
where 和 having
7. case when 和 decode
知识准备
1. sql执行过程
1)执行过程
当一个oracle实例接收到一条sql后,执行过程如下:
1) create a cursor 创建游标
2) parse the statement 分析语句
3) describe results of a query 描述查询的结果集
4)define output of a query 定义查询的输出数据
5)bind any variables 绑定变量
6)parallelize the statement 并行执行语句
7)run the statement 运行语句
8)fetch rows of a query 取查询结果
9)close the cursor 关闭游标
2.SQL 共享
1.为不重复解析相同的SQL语句,oracle 将执行过的SQL语句存放在内存的共享池(shared buffer pool)中,可以被所有数据库用户共享
2. 当执行一个SQL语句时,如果它和之前执行过的语句完全相同(注意同义词和表是不同对象),oracle就能获得已经被解析的语句;
3.bind variables绑定变量
1)解决重编译问题
eg1:
insert into tab1(col1,col2) values (val1,val2); --普通方式
insert into tab1(col1,col2) values (:v1,:v2);--绑定变量,只需编译一次
eg2:使用PreparedStatement
PreparedStatement ps = con.prepareStatement("insert into tab1 (col1, col2) values (?,?)");
2)共享游标
好处:减少解析;提高内存使用率;动态内存调整
假如输入如下两个sql:
select * from tab1 where id = :c;
select * from tab1 where id = :d;
这两句sql会被转化为:
select * from tab1 where id = :b;
4.访问数据表方式
1)全表扫描——顺序访问表中每条记录
oracle采用一个读入多个数据块的方式优化全表扫描
2)通过rowid访问表——rowid包含了表中记录的物理位置信息, 基于rowid访问方式可以提高访问表的效率
oracle通过索引实现了数据和存放数据位置rowid之间的联系,通常索引提供了快速访问rowid的方法
5. select sql执行顺序
1)select子句
(8)SELECT (9)DISTINCT (11)<Top Num> <select list>
(1)FROM <left_table>
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>
2)执行顺序说明
1)FROM [left table]——from前的表做笛卡尔集 ——虚拟表VT1
2) ON <join condition>——筛选——VT2
3) [join type] JOIN [right table]——连接——VT3 详细见 oracle连接
4) WHERE ——where筛选——VT4
5)GROUP BY ——按照GROUP BY子句中的列对VT4中行分组——VT5
6)CUBE|ROLLUP——分组,eg:ROLLUP(A, B),首先会对(A、B)进行GROUP BY,然后对(A)进行GROUP BY,最后对全表GROUP BY
CUBE(A,B), 首先对(A、B)GROUP BY, 然后(A)、(B) GROUP BY, 最后全表GROUP BY;
——VT6
7) HAVING——HAVING筛选——VT7
8)SELECT——VT8
9) DISTINCT——移除重复的行——VT9
10)ORDER BY——按照order by子句中的列将VT9中列表排序,生成游标——VC10
11) TOP ——从VC10的开始处选择一定数量或者比例的行——VT11,返回结果
3)注意事项
1. 只有ORDER BY 子句中可以使用select列表中列的别名
如果要在其他地方使用需要使用如下方式:
SELECT * FROM (SELECT NAME, SALARY AS s FROM EMP ) vt WHERE vt.s<5000;
2. 使用了ORDER BY子句的查询不能用作表表达式(视图、内联表值函数、子查询、派生表和共用表达式),如下的语句都会产生错误
create table tab1 as select * from student order by score;
select * from (select * from student order by score);
6.索引使用
正确使用索引可以有效提高系统性能,详细见oracle索引总结
常用sql用法和及注意事项
1.exits和in用法
1)说明:
1.exists对外表做循环,每次循环对内表查询;in将内表和外表做hash连接
2. 使用exists oracle会先检查主查询; 使用in,首先执行子查询,并将结果存储在临时表中
2)使用:
表class和student表
下面查询student中classno在class中的数据
1.使用exists和not exists
select name, classno from student where exists (select * from class where student.classno= class.classno);
结果:
select name, classno from student where not exists (select * from class where student.classno= class.classno);
结果:
select name, classno from student where classno in (select classno from class);
2.使用in 和not in
select name, classno from student where classno not in (select classno from class);
结果:
3)比较
1. 如果两个表大小相当,in和exists差别不大
2. 如果两个表大小相差较大则子查询表大的用exists,子查询表小的用in
3.尽量不要使用not in
2.union和union all
1)说明:
1. 使用场景:需要将两个select语句结果整体显示时,可以使用union和union all
2. union对两个结果集取并集不包含重复结果同时进行默认规则的排序;而union all对两个结果集去并集,包括重复行,不进行排序
3. union需要进行重复值扫描,效率低,如果没有要删除重复行,应该使用union all
4. insersect和minus分别交集和差集,都不包括重复行,并且进行默认规则的排序
2)使用注意事项
1.可以将多个结果集合并
2. 必须保证select集合的结果有相同个数的列,并且每个列的类型是一样的(列名不一定要相同,会默认将第一个结果的列名作为结果集的列名)
3)例子:
表student
eg1:
select name, score from student where score> 60
union all
select name, score from student where score <200;
结果:(有重复,没有排序)
select name, score from student where score> 60
union
select name, score from student where score <200;
结果:(没有重复,并且排序了)
3.with as
1)说明:
1. with table as 可以建立临时表,一次分析,多次使用
2. 对于复杂查询,使用with table as可以抽取公共查询部分,多次查询时可以提高效率
3. 增强了易读性
2)语法:
with tabName as (select ...)
3)例子:
表student
eg1:
select rownum, name, score from (select rownum, name,score from student where score >70 order by score);
可以更换成:
with table_s as (select rownum, name,score from student where score >70 order by score)
select name, score from table_s;
结果:
4)多个with table as 一起使用时用逗号隔开,并且只能使用一个with如下例子
eg1:
with vt1 as (select * from student where score >=60),
vt2 as (select * from class),
vt3 as (select * from teacher)
select vt1.name, vt1.score, vt2.classname, vt3.teachername from vt1,vt2,vt3 where vt1.classno= vt2.classno and vt1.teacherid=vt3.teacherid;
eg2:
with vt as (select t.*
from travelrecord t where t.starttime>=to_date('2014-02-01','yyyy-mm-dd') and t.endtime<=to_date('2014-04-30','yyyy-mm-dd')+1 and to_char(starttime,'hh24')>='08' and to_char(endtime,'hh24')<='11' and t.vehiclenum='100088110000'),
vt1 as (select sum(vt4.traveltime) as stoptime from ((select * from vt where vt.state='0')vt4)),
vt2 as (select sum(vt.traveltime)as "ONLINETIME1",sum(vt.distance)as "DISTANCE1"from vt)
select vt1.stoptime,vt2.distance1, vt2.onlinetime1 from vt2, vt1;
4. order by
1)说明:
1. order by 决定oracle如何将查询结果排序
2. 不指定asc或者desc时默认asc
2)使用:
1. 单列升序(可以去掉asc)
select * from student order by score asc;
2. 多列升序
select * from student order by score, deptno;
3. 多列降序
select * from student order by score desc, deptno desc;
4. 混合
select * from student order by score asc, deptno desc;
3)对NULL的处理
1. oracle在order by 时认为null是最大值,asc时排在最后,desc时排在最前
eg:
select * from student order by score asc;
结果:
2. 使用nulls first (不管asc或者desc,null记录排在最前)或者nulls last 可以控制null的位置,eg:
select * from student order by score asc nulls first;
结果如下:
4)将某行数据置顶(decode)
eg1:
select * from student order by decode(score,100,1,2);
结果:
eg2: (某一行置顶,其他的升序)
select * from student order by decode(score,100,1,2), score;
5)注意事项
1.任何在order by 语句的非索引项都将降低查询速度
2. 避免在order by 子句中使用表达式
5. group by
1)说明:
1.用于对where执行结果进行分组
2)简单例子:
eg1:
select sum(score), deptno from student group by deptno;
结果:
eg2:
select deptno,sum(score) from student where deptno>1 group by deptno;
结果:
6.where和having
1)说明:
1. where和having都是用来筛选数据,但是执行的顺序不同 where --group by--having(即分组计算前计算where语句,分组计算后计算having'语句),详情查看章节一sql执行顺序
2. having一般用来对分组后的数据进行筛选
3. where中不能使用聚组函数如sum,count,max等
2)例子:
eg1: 对 5 中group by 的数据筛选
select deptno,sum(score) from student where deptno>1 group by deptno having sum(score)>100;
结果:
7. case when 和decode
1)说明:
1. decode更简洁
2. decode只能做等值的条件区分,case when可以使用区间的做判断
2)语法:
decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值)
--等价于:
IF 条件=值1 THEN
RETURN(翻译值1)
ELSIF 条件=值2 THEN
RETURN(翻译值2)
......
ELSIF 条件=值n THEN
RETURN(翻译值n)
ELSE
RETURN(缺省值)
END IF
CASE expr WHEN comparison_expr1 THEN return_expr1
[WHEN comparison_expr2 THEN return_expr2
WHEN comparison_exprn THEN return_exprn
ELSE else_expr]
END
CASE
WHEN comparison_expr1 THEN return_expr1
[WHEN comparison_expr2 THEN return_expr2
WHEN comparison_exprn THEN return_exprn
ELSE else_expr]
END
3)例子:
eg1:
方式一:
select name, score,gender,
case gender when '1' then '女'
when '2' then '男'
else '未说明'
end gender_t
from student;
方式二:
select name, score,gender,
case when gender='1' then '女'
when gender='2' then '男'
else '未说明'
end gender_t
from student;
方式三:
select name,gender,decode(gender,'1','女','2','男','未说明')gender_t from student;
结果:
eg2:
select name,score,
case when score >80 then'优秀'
when score>=60 and score <=80 then '良好'
when score<60 then '不及格'
end evalution
from student;
结果:
设置默认值,将null置为没成绩:
select name,score,
case when score >80 then'优秀'
when score>=60 and score <=80 then '良好'
when score<60 then '不及格'
else '没成绩'
end evalution
from student;
结果:
4)注意:
1.case有两种形式,其中case 表达式 when then方式效率高于case when 表达式效率
2.使用decode函数可以避免重复扫描相同记录或者重复连接相同的表,因而某些情况可以减少处理时间
SQL 优化总结
1. SQL优化一般性原则
1)目标:减少服务器资源消耗(主要是磁盘IO)
2)设计:
1. 尽量依赖oracle优化器
2. 合适的索引(数据重复量大的列不要简历二叉树索引,可以使用位图索引; 对应数据操作频繁的表,索引需要定期重建,减少失效的索引和碎片)
3)编码:
1.利用索引
2. 合理利用临时表
3. 避免写过于复杂的sql;
4. 尽量减小事务的粒度
2. 具体注意事项
1)查询时尽量使用确定的列名
2)尽量少使用嵌套的子查询,这种查询很消耗cpu资源
3)多表查询的时候,选择最有效率的表名顺序
oracle解析器对表的处理顺序从右到左,所以记录少的表放在右边(最右边的表为基础表,drivering table最先被处理), 如果3个以上的表连接查询,则要选择交叉表作为基础表
4)or比较多时分为多个查询,使用union all(尽量用union all代替union)联结(适应于索引列)
详细见上一章节union和union all
5) 尽量多用commit提交事务,可以及时释放资源、解锁、释放日志
6)访问频繁的表可以放置在内存中
7)避免复杂的多表关联
8)避免distinct,union(并集),minus(差集),intersect(交集),order by等耗费资源的操作,因为会执行耗费资源的排序功能
9)使用exists替代distinct
eg:
select c.distinct c.classname, c.classid, classno from student s, class c where s.classno= c.classno;
--替换为
select classname, classid, classno from class c where exists (select * from student s where s.classno = c.classno);
10)删除全表时利用truncate代替delete
delete删除时,没有commit前可以回滚;truncate后不能回滚,执行时间较短
11)使用表的别名,可以减少解析时间
12)exists和in的选择问题,不同时候区分对待
具体见上一章节exists和in
13)合理使用索引,详细见:oracle索引总结
分享到:
相关推荐
Oracle SQL 优化 Oracle SQL 优化是数据库性能优化的关键部分。为了提高数据库的性能,我们需要从五个方面进行调整:去掉不必要的大型表的全表扫描、缓存小型表的全表扫描、检验优化索引的使用、检验优化的连接技术...
### ORACLE中SQL查询优化技术 #### 一、引言 在现代企业级数据库应用中,Oracle数据库因其高性能、高可靠性和丰富的功能被广泛采用。然而,在实际的应用场景下,即使是设计良好的数据库系统也可能因为查询效率低下...
Oracle SQL 性能优化 Oracle SQL 性能优化是数据库管理中非常重要的一环。通过对 SQL 语句执行的过程、Oracle 优化器、表之间的关联、如何得到 SQL 执行计划、如何分析执行计划等内容的讨论,可以逐步掌握 SQL ...
基于Oracle的SQL优化
- **SQL优化机制**: - **SQL语句处理过程**:理解SQL语句在Oracle中的处理流程对于优化至关重要。 - **共享SQL区域**:Oracle会在内存的共享池中缓存已执行过的SQL语句,以便后续执行时可以直接使用而无需重新...
根据提供的文件信息,本文将对《基于Oracle的SQL优化》这一主题进行深入解析,包括但不限于SQL优化的重要性、Oracle数据库的特点以及具体的SQL优化方法等。 ### SQL优化的重要性 SQL(Structured Query Language)...
教主Oracle SQL高级查询优化改写完美培训视频 2.0版,这个我参与培训的,包含视频、SQL文件、教学文档内容完整,分享给大家学习,共同努力进阶转型开发DBA,人称教主,做sql改写十多年了,sql改写功底很强!
基于Oracle的SQL优化
《Oracle SQL性能优化》这本书是数据库管理员和开发人员的重要参考资料,它深入探讨了如何提高Oracle数据库的SQL查询性能。在数据库系统中,SQL查询的速度直接影响到应用的响应时间和整体性能,因此,理解并掌握SQL...
这个"Oracle_SQL优化脚本_完整实用资源"压缩包包含了一系列工具和方法,旨在帮助你优化在Oracle数据库上运行的SQL查询,从而提高数据库的响应速度和整体效率。 1. **SQL执行计划分析**:在Oracle中,通过`EXPLAIN ...
ORACLE SQL性能优化.chm ORACLE SQL性能优化.chm ORACLE SQL性能优化.chm
Oracle SQL 优化技巧 Oracle SQL 优化是提高数据库性能的关键技巧之一。以下是 Oracle SQL 优化的 12 个技巧: 1. 选择最有效率的表名顺序 在基于规则的优化器中,Oracle 的解析器按照从右到左的顺序处理 FROM ...
SQL优化是数据库管理中的关键环节,它涉及到提升查询性能、减少资源消耗以及改善系统整体效率。SQL优化软件和工具能够帮助数据库管理员(DBA)和开发人员找出性能瓶颈,优化查询逻辑,从而提高数据库系统的响应速度...
主要讲述oracle sql 的开发以及优化,对低效率的sql的优化方法和诊断技巧
Oracle Sql性能优化 解宝喆 1、选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在...
本文将深入探讨Oracle数据库查询优化的各种方法和技术。 首先,我们从SQL语句的编写入手。良好的SQL编写习惯是优化的基础。应避免使用全表扫描,尽可能利用索引来加速查询。索引是数据库中用于快速查找记录的一种...
Oracle SQL性能优化是一个复杂且重要的主题,涉及到数据库的多个层面,包括优化...通过理解和应用这些策略,数据库管理员和开发人员可以显著提升Oracle SQL查询的性能,降低数据库系统的总体响应时间,并优化资源使用。