SQL优化二(Sql性能调优)
一·、前言
二、ORACLE服务器
三、分析语句阶段优化
- RBO(rule-base optimizer):优化器遵循Oracle内部预定的规则,句法驱动和数据字典驱动。
- CBO(cost-based optimizer):依据语句执行的代价,主要指对CPU和内存的占用,优化器在判断是否使用CBO时,要参照表和索引的统计信息统计表驱动,统计信息要在对表做analyze后才会有。
Oracle优化器的优化模式主要有五种:
- Choose:默认模式。根据表或索引的统计信息,如果有统计信息,则使用CBO方式;如果没有统计信息,相应列有索引,则使用RBO方式。
- Rule:基于规则优化,忽略任何统计信息
- First rows:与Choose类似。不同的是如果表有统计信息,它将以最快的方式返回查询结果,以获得最佳响应时间。
- First_rows_n:与Choose类似。不同的是如果表有统计信息,它将以最快的方式返回查询的前几行,以获得最佳响应时间。
- All rows:完全基于CBO的模式。当一个表有统计信息时,以最快方式返回表所有行,以获得最大吞吐量。没有统计信息则使用RBO方式。
Oracle Optimizer 运行级别怎么修改?
- Instance级:修改启动参数在init<SID>.ora文件中设定OPTIMIZER_MODE,需要数据库重启
- Session级:(JDBC或者Hibernate或者一次连接),通过alter session set optimizer_mode = value修改,忽略instance级
- Statement级:通过在SQL语句中加如Hint(隐语)实现,表明对语句块选择基于开销的优化方法,并获得最佳响应时间,忽略instance级和session级
SELECT /*+ALL_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';
DBMS_STATS包工具做CBO代价分析
分析用户所有的对象(包括表、索引、簇):gather_schema_stats
分析表:gather_table_stats
分析索引:gather_index_stats
删除数据库统计信息:delete_database_stats
删除用户方案统计信息:delete_schema_stats
删除表统计信息:delete_table_stats
删除索引统计信息:delete_index_stats
删除列统计信息:delete_column_stats
设置表统计信息:set_table_stats
设置索引统计信息:set_index_stats
设置列统计信息:set_column_stats
可以查看表 DBA_TABLES来查看表是否与被分析过,如:
SELECT TABLE_NAME, LAST_ANALYZED FROM DBA_TABLES
通常使用的比较多的主要是DBMS_STATS.GATHER_TABLE_STATS和 DBMS_STATS.GATHER_INDEX_STATS。
2 dbms_stats.create_stat_table(ownname =>
'scott',stattab => 'STAT_TABLE');
3 end;
4 /
ownname => 'SCOTT',
options => 'GATHER AUTO',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all columns size repeat',
degree => 15
)
四、执行计划阶段优化
全表扫描(Full Table Scans)
通过ROWID的表存取(Table Access by ROWID)
ROWID记录了记录行所在的数据文件、数据块以及行在该块中的位置,所以通过ROWID来存取数据可以快速定位到目标数据上,可以说是整个数据库都在用的索引,是Oracle存取单行数据的最快方法。这种存取方法不会用到多块读操作,一次I/O只能读取一个数据块。
select empno from emp where rowid='AAAR3sAAEAAAACXAAA';
索引扫描(Index Scan)
索引唯一扫描(index unique scan)
通过唯一索引查找一个数值经常返回单个ROWID,如果存在UNIQUE 或PRIMARY KEY 约束(约束只有一行记录匹配),Oracle实现索引唯一性扫描。
select empno from emp where empno=7369;
索引范围扫描(index range scan)
使用一个索引存取多行数据,在唯一索引上使用索引范围扫描的典型情况下是在谓词(where限制条件)中使用了范围操作符,有以下三种情况会导致引起索引范围扫描:
- 在唯一索引列上使用了range操作符(> < <> >= <= between)
- 在组合索引上,只使用部分列进行查询,导致查询出多行
- 对非唯一索引列上进行的任何查询。
select empno from emp where empno>7369;
索引全扫描(index full scan)
什么时候会引起索引全扫描呢?当不使用谓词逻辑where;所有查询结果数据都必须从索引中可以直接得到;需要排序操作,比如order by。
select empno from emp order by empno;
index full scan使用单块读方式有序读取索引块,产生db file sequential reads事件,当采用该方式读取大量索引全扫描,效率低下
索引快速扫描(index fast full scan)
与索引全扫描很相似,只是不涉及排序动作。
select /*+ index_ffs(emp pk_emp) */empno from emp; //对指定的表执行快速全索引扫描,而不是全表扫描的办法.
index fast full scan使用多块读的方式读取索引块,产生db file scattered reads 事件,读取时高效,但为无序读取
优化技巧7:对于只从表中查询出总行数的2%到4%行的表时,可以考虑创建索引。
优化技巧8:不要将那些频繁修改的列作为索引列,频繁修改会导致不必要的索引开销。
优化技巧9:不要使用包含函数或操作符放入WHERE从句中的关键字作为索引,会导致索引失效,可以考虑使用函数索引。
优化技巧10:在组合索引中,没有按照建立时的索引关键字顺序描述,比如xyz变成了yxz,也会导致索引失效。
优化技巧11:如果在表中要建立索引的一列或多列上使用了函数或表达式,则创建的是基于函数的索引。基于函数的索引预先计算函数或表达式的值,并将结果存储在索引中。B树索引和bitmap索引也是函数索引
优化技巧12:排序动作能不做就不做,增加系统开销的同时还会使快速索引失效。
备注:
#函数索引
CREATE INDEX idx ON table_1 (a + b * (c - 1), a, b);
# 则可以在查询语句中使用函数索引:
SELECT a
FROM table_1
WHERE a + b * (c - 1) < 100;
五、多表关联查询操作
排序合并连接(Sort Merge Join (SMJ))
select aa.CREATEPERSONNAME, bb.CREATEPERSON
from tbl_comm_commonticket aa, tbl_ybgz_ticket bb
where aa.CREATEPERSONNAME = bb.CREATEPERSON
order by aa.CREATEPERSONNAME, bb.CREATEPERSON
排序属于代价很高的操作,特别对于大表。因此经常避免使用排序合并连接方法,但是如果2个row source都已经预先排序(比如primary Key索引),则这种连接方法可以选用。
嵌套循环(Nested Loops (NL))
分为驱动表(OUTER TABLE)和内层表(INNER TABLE)。因为嵌套循环,所以外层循环的次数越少越好,因此一般将数据量较小表或满足条件的row source较小的表作为驱动表(用于外层循环)的理论依据。
select /*+USE_NL(emp,dept)*/ * from emp,dept where emp.deptno=dept.deptno;
嵌套循环返回已经连接的行,而不必等待所有的连接操作处理完才返回数据 ,所以提高了响应速度。如果OUTER TABLE比较小,并且在INNER TABLE上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。另外,这种连接方式,是在RBO优化器中。
哈希连接(Hash Join)
散列基本原理是:使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数,也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素;但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中。 总的来说,“直接定址”与“解决冲突”是哈希表的两大特点。
散列连接是CBO 做大数据集连接时的常用方式,优化器使用两个表中较小的表(或数据源)利用连接键在内存中建立散列表,然后扫描较大的表并探测散列表,找出与散列表匹配的行。
hash join只有在CBO方式下可以使用;Oracle初始化参数HASH_JOIN_ENABLED决定是否启用hash join;pga_aggregate_target指定散列连接可用的内存大小;尽量使内层表生成的散列表最小,最好能够全部载入内存;主要用于等值连接。
select /*+USE_HASH(emp,dept)*/ * from emp,dept where emp.deptno=dept.deptno;
六、其他
优化技巧13:避免使用不确定操作符<>,!= 或者 where 子句中使用 or 来连接条件,因为会引起全表扫描; or 可以用union或者(union all) 代替。
select * from emp where empno>7369 union select * from emp where empno<7369;
优化技巧14:Where子句中出现IS NULL或者IS NOT NULL时,Oracle会停止使用索引而执行全表扫描。可以在设计表时,对索引列设置为NOT NULL。这样就可以用其他操作来取代判断NULL的操作。
优化技巧15:当通配符“%”或者“_”作为查询字符串的第一个字符时,索引不会被使用 。
优化技巧16:对数据类型不同的列进行比较时,会使索引失效。
优化技巧17:UNION操作符会对结果进行筛选,消除重复,数据量大的情况下可能会引起磁盘排序。如果不需要删除重复记录,应该使用UNION ALL。
SQL> select deptno from emp union select deptno from dept;
SQL> select deptno from emp union all select deptno from dept;
优化技巧18:Order By语句中的非索引列会降低性能,可以通过添加索引的方式处理。严格控制在Order By语句中使用表达式。
优化技巧19:相同的Sql语句,要保证查询字符完全相同,大小写,空格位置,利用shared_pool,防止相同的Sql语句被多次分析,使用变量绑定。
优化技巧20:调整SQL语句的目的是为了在执行中使资源的使用减少到最小。除了选择使用不同的SQL语法来优化执行代价,还可以通过调整执行顺序优化SQL。
优化技巧21:Oracle在执行IN子查询时,首先执行子查询,将查询结果放入临时表再执行主查询。而EXIST则是首先检查主查询,然后运行子查询直到找到第一个匹配项。因此NOT EXISTS比NOT IN效率稍高,相应更快。但是(NOT) EXISTS 不等于(NOT) IN。
SQL>select * from emp where deptno in (select deptno from dept);
SQL>select * from emp where exists (select deptno from dept where emp.deptno=dept.deptno);
优化技巧22:可以多使用视图进行软解析,视图只是把你要用的sql进行保存而已,你需要担心的是视图中的sql会不会效率太低,而不用担心视图的耗时。
优化技巧23:适当的时候强制使用rule会获得更高效率;调试SQL时关注执行计划和执行代价。
优化技巧24:避免视图嵌套使用,尤其是针对视图排序,筛选等操作。
优化技巧25:不同版本数据库的执行计划差别可能很大。
优化技巧26:不是只有select..是查询,所有的DML操作都含有查询过程。
七、SQL分析工具
SQL优化二(Sql性能调优)的更多相关文章
- SQL Server 列存储性能调优(翻译)
原文地址:http://social.technet.microsoft.com/wiki/contents/articles/4995.sql-server-columnstore-performa ...
- Spark SQL概念学习系列之性能调优
不多说,直接上干货! 性能调优 Caching Data In Memory Spark SQL可以通过调用sqlContext.cacheTable("tableName") 或 ...
- Spark(十二)--性能调优篇
一段程序只能完成功能是没有用的,只能能够稳定.高效率地运行才是生成环境所需要的. 本篇记录了Spark各个角度的调优技巧,以备不时之需. 一.配置参数的方式和观察性能的方式 额...从最基本的开始讲, ...
- Linux性能优化之内存性能调优
一.根据性能指标找工具 二.根据工具查性能 三.内存优化策略 常见的优化思路有这么几种: 1)最好禁止 Swap.如果必须开启 Swap,降低 swappiness 的值,减少内存回收时 Swap 的 ...
- 记一次sql server 性能调优,查询从20秒至2秒
一.需求 需求很简单,就是需要查询一个报表,只有1个表,数据量大约60万左右,但是中间有些逻辑. 先说明一下服务器配置情况:1核CPU.2GB内存.机械硬盘.Sqlserver 2008 R2.Win ...
- 如何合理的规划一次jvm性能调优
https://blog.csdn.net/miracle_8/article/details/78347172 摘要: JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的 ...
- [Spark性能调优] 第一章:性能调优的本质、Spark资源使用原理和调优要点分析
本課主題 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- 性能调优的本质、Spark资源使用原理和调优要点分析
本课主题 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- OCM_第十四天课程:Section6 —》数据库性能调优_各类索引 /调优工具使用/SQL 优化建议
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- 二十种实战调优MySQL性能优化的经验
二十种实战调优MySQL性能优化的经验 发布时间:2012 年 2 月 15 日 发布者: OurMySQL 来源:web大本营 才被阅读:3,354 次 消灭0评论 本文将为大家介 ...
随机推荐
- 我的学习之路_第二十七章_jQuery
jQueryjs类库 把常用对象或者方法封装起来,让我们写代码效率更高 1.jQuery 2.extjs [jQuery入门] jQuery的引入: 通过script标签的src属性引入 入门: 获取 ...
- 谈谈HashMap与HashTable
谈谈HashMap与HashTable HashMap 我们一直知道HashMap是非线程安全的,HashTable是线程安全的,可这是为什么呢?先聊聊HashMap吧,想要了解它为什么是非线程安全的 ...
- JS - 讨论 - 编码习惯 - JavaScript代码到底要不要写分号?
如题:烦请大家在评论区给出原创意见!多谢!
- Spring和SpringMVC父子的容器之道---[上篇]
Spring和SpringMVC作为Bean管理容器和MVC层的默认框架,已被众多WEB应用采用,而在实际开发中,由于有了强大的注解功能,很多基于XML的配置方式已经被替代,但在实际项目中,我们经常会 ...
- linux执行sh报错:$’\r’: 未找到命令的解决
背景 执行.sh脚本时出现$'\r': 未找到命令, 原因 是因为命令直接从windows 复制过来导致的 解决 yum install dos2unix dos2unix **.sh 进行转换 再次 ...
- Java开源博客My-Blog(SpringBoot+Docker)系列文章
My Blog 1.Docker+SpringBoot+Mybatis+thymeleaf的Java博客系统开源啦 2.My-Blog搭建过程:如何让一个网站从零到可以上线访问 3.将数据的初始化放到 ...
- (转)目前比较全的CSS重设(reset)方法总结
在当今网页设计/开发实践中,使用CSS来为语义化的(X)HTML标记添加样式风格是重要的关键.在设计师们的梦想中都存在着这样的一个完美世界:所有的浏览器都能够理解和适用多有CSS规则,并且呈现相同的视 ...
- c++ vector(向量)使用方法详解(顺序访问vector的多种方式)
来源:http://www.jb51.net/article/44231.htm 作者: 字体:[增加 减小] 类型:转载 时间:2013-12-08我要评论 vector是向量类型,它可以容纳许多类 ...
- Mybatis源码解析-MapperRegistry注册mapper接口
知识储备 SqlsessionFactory-mybatis持久层操作数据的根本,具体的解析是通过SqlSessionFactoryBean生成的,具体的形成可见>>>Spring ...
- Android APP 内部捐赠实现(支付宝&微信)
Android APP 内部捐赠实现(支付宝&微信) 目前支持 支付宝和 微信. 项目地址:https://github.com/didikee/AndroidDonate https://p ...