( O管理)ORACLESL性能优化(内部培训资料)

合集下载

推荐下载-Oracle数据库优化培训 精品

推荐下载-Oracle数据库优化培训 精品
SELECT A.MDSE_ID, FROM MDSE A, DIM_MDSE_SPEC B
WHERE A.MDSE_SPEC_ID = B.MDSE_SPEC_ID
SELECT MDSE_ID, MDSE_SPEC_ID FROM MDSE
ORDER BY MDSE_ID, MDSE_SPEC_ID
B) SELECT * FROM SERV T
WHERE T.PLACE_S_NODE = 600488 AND T.INTEGRAL = 594000248;
C)SELECT * FROM SERV T
WHERE T.PLACE_S_NODE = 600488 AND T.STATE = 'A';
什么是优化器
查询优化对提高查询效率是至关重要的,在任何一 个商品化的RDBMS中,都必须有一个专门负责查询语 句优化的程序,称为优化器;是SQL之前分析语句的工 具。
优化器的优化方式:
基于规则(RBO): 优化器遵循Oracle内部预定的规则
基于代价(CBO): 依据语句执行的代价,主要指对CPU和内存的占用。
SELECT NAME,MDSE_SPEC_ID FROM DIM_MDSE_SPEC
ORDER BY NAME, MDSE_SPEC_ID
SELECT A.MDSE_ID, FROM A, B
WHERE A.MDSE_SPEC_ID = B.MDSE_SPEC_ID
多表连接的优化处理——连接方式
备注:比索引合并更有效的方法是建立组合索引 组合索引有两种使用方式:全部说明方式和部分说明方式。 全部说明方式:组合索引列全部出现在查询中。 部分说明方式:组合索引列前面一部分出现在查询中。

oracle_sql优化培训课程

oracle_sql优化培训课程

优化一.培训目的数据库参数进行优化所获得的性能提升全部加起来只占数据库应用系统性能提升的左右,其余的系统性能提升全部来自对应用程序的优化。

许多优化专家甚至认为对应用程序的优化可以得到的系统性能提升。

因此可以肯定,通过优化应用程序来对、备份数据库和清除垃圾数据。

、语句语法的优化。

、清理删除日志。

三.语句优化的原则:的优化器优化器有时也被称为查询优化器,这是因为查询是影响数据库性能最主要的部分,不要以为只有语句是查询。

实际上,带有任何条件的 (、、)语句中都包含查询要求,在后面的文章中,当说到查询时,不一定只是指语句,也有可能指语句中的查询部分。

优化器是所有关系数据库引擎中的最神秘、最富挑战性的部件之一,从性能的角度看也是最重要的部分,它性能的高低直接关系到数据库性能的好坏。

我们知道,语句同其它语言(如语言)的语句不一样,它是非过程化()的语句,即当你要取数据时,不需要告诉数据库通过何种途径去取数据,如到底是通过索引取数据,还是应该将表中的每行数据都取出来,然后再通过一一比较的方式取数据(即全表扫描),这是由数据接条件和()。

并抛弃其方法( )一个判断条件,如””, “>”, ”<”等),而且该谓词上引用的列上有有效索引,那么优化器将使用索引访问这个表,而不考虑其它因素,如表中数据的多少、表中数据的易变性、索引的可选择性等。

此时数据库中没有关于表与索引数据的统计性描述,如表中有多上行,每行的可选择性等。

优化器也不考虑实例参数,如、可用排序内存的大小等,所以优化器有时就选择了次优化的计划作为真正的执行计划,导致系统性能不高。

如,对于* ;这个查询来说,如果是使用基于规则的优化器,而且列上有有效的索引,则会通过列上的索引来访问表。

在绝大多数情况下,这是比较高效的,但是在一些特殊情况下,使用索引访问也有比较低效的时候,现举例说明:1)表比较小,该表的数据只存放在几个数据块中。

此时使用全表扫描比使用索引访问表反而要好。

Oracle 10g 数据库性能优化最佳实战培训课程

Oracle 10g 数据库性能优化最佳实战培训课程

附件1. 培训大纲附件2 .公司简介中睿信息技术有限公司是一家专业的IT服务供应商,致力于高级IT技术培训、解决方案实施、软件咨询服务,公司以“领航IT服务”为企业愿景,与微软(Microsoft)、甲骨文(Oracle)、思科(Cisco)、BEA等全球多家跨国IT厂商建立长期的合作伙伴关系,汇集了全国众多顶级IT培训讲师和具备丰富理论与实战经验的技术精英,不断为追求卓越的企业提供最有价值的培训与服务,致力于培养具备综合实战经验及技能的复合型IT人才。

中睿信息技术有限公司立足IT服务与培训行业,为您传递与全球同步的信息技术,我们用心做到:至诚服务·创造价值∙业务范围一、IT培训∙系统与网络:Windows Server、Exchange、MOSS、SCCM、SCOM、CCNA、Linux、Unix…∙数据库:SQL Server、Oracle∙软件开发与软件工程:.NET系列、Java系列、中间件、OOAD、UML、SOA…∙IT管理类:IT项目管理、IT服务管理(ITIL)、软件项目管理…∙Office办公:Word、Excel、Outlook、PowerPoint、InfoPath、Access…二、IT服务顾问咨询服务:软件开发管理、项目管理∙软件开发过程的规范咨询∙软件分析、设计的实现、审核与优化∙软件系统体系架构的规划、设计与审核∙软件系统需求开发与管理∙信息规划及项目管理年度服务:按年度签约的合作方式提供企业IT顾问咨询、规划与部署、定期巡检、技术答疑等服务。

项目服务:针对企业IT现状及需求,为企业提供最佳解决方案,确保企业IT应用的稳定性及高可用性。

∙AD(活动目录)架构规划与部署∙Exchange邮件系统规划与部署∙Exchange邮件系统升级与迁移∙企业客户端标准化及管理解决方案(SCCM)∙企业应用服务集中监控解决方案(SCOM)∙统一沟通解决方案(UC)∙商业智能解决方案(MOSS)∙用户身份认证解决方案(ILM)∙内容管理解决方案(MOSS)∙商业流程解决方案(MOSS)∙数据库现场安装、升级、迁移服务(ORALCE)∙数据库健康检查、性能评估及优化调整服务(ORALCE)∙数据库规划、设计、容灾服务(ORALCE)…………紧急技术支持服务:当企业的信息系统遇到突发事件,并严重影响正常业务运行,可提供7*24小时紧急上门服务,在最短的时间内解决问题,避免突发事件给企业带来的影响和降低造成的损失。

Oracle数据库性能优化

Oracle数据库性能优化

例子3——优化前
select b.insuredname, b.insuredidno
from llclaimpedor a, lccont b where trim(a.contno) = trim(b.contno)
and a.caseno = '9055000006018488'
例子3——优化后
例子4——优化后
SELECT r.* FROM LOPRTManager r, LCCont t WHERE r.StateFlag in ('1') and (patchflag is null or patchflag <> '1') and r.Code <> '70' AND r.PrtType = '0' and t.ContNo = r.OtherNo and r.ManageCom like '86070101%' union all SELECT r.* FROM LOPRTManager r WHERE r.StateFlag in ('1') and (patchflag is null or patchflag <> '1') and r.ManageCom like '86070101%' AND r.PrtType = '0' and r.Code = '70' and r.PrtSeq = '1019010000132388' and r.PrtSeq = '1019010000132388'
索引创建原则
提高查询语句的效率,减慢了DML语句的速度 在全表扫描和索引之间权衡 在哪些列建立索引 Where字句中引用的列 Join中引用的列 在子表的FK上建立索引 • 防止对父表操作时锁住子表 在哪些列上不要建立索引 经常有DML操作 排它性小 Select count(1),count(distinct col_name ) from table_name

oracle开发优化培训

oracle开发优化培训
• • • • 使用统一的SQL开发规范 尽量使SQL简单,否则请设计人员修改设计 尽量减少数据库访问次数 合理使用绑定变量(列值分布均匀) ,日期、时间 列慎用 • 查询条件中的常量尽量引用同一个表 • 确保变量及常量要与字段类型一致 • 在确保事务完整的前提下及时COMMIT
SQL性能优化原则
SQL性能调优方法—了解ORACLE优化器
OPTIMIZER_MODE
• • • • • CHOOSE: 基于统计信息,cost-based ALL_ROWS:以最小资源消耗为目标 FIRST_ROWS_N:(n=1, 10, 100, 1000 ) FIRST_ROWS:以最少时间为目标 RULE:按照预先制定的规则执行
SQL性能调优方法—了解ORACLE优化器
SQL性能调优方法—了解ORACLE优化器
SQL性能调优方法—查看执行计划
在SQL*PLUS中查看执行计划
SET AUTOT[RACE]{OFF|ON|TRACE[ONLY]} [EXP[LAIN]][STAT[ISTICS]]
SQL>SET AUTOT ON SQL>SET AUTOT TRACEONLY
SQL优化开发原则及调优方法
• 事前优化的原则 • SQL性能调优方法
SQL性能优化原则
影响性能的主要因素
• • • • • 硬件问题 系统设计问题 表存储结构及索引设置问题 SQL编写问题 运行参数设置问题
SQL性能优化原则
不同优化阶段性能收益
效 果
生命周期
设计阶段
开发阶段
化原则
绑定变量的实现方法 • 存储过程中,直接使用变量就可以 例:select * from emp where empno=ls_empno;

oracle培训讲义(性能分析与调整).doc

oracle培训讲义(性能分析与调整).doc

性能分析与调整1.Oracle 的SQL 执行计划2.Auto_trace1) 设置步骤:SQL> conn system/oracle 已连接。

SQL> start ?\rdbms\admin\utlxplan 表已创建。

SQL> create public synonym plan_table for plan_table; 同义词已创建。

SQL> grant all on plan_table to public;授权成功。

SQL> conn sys/oracle as sysdba 已连接。

SQL> start ?\sqlplus\admin\plustrceSQL> drop role plustrace;drop roleplustraceSQL> create role plustrace;角色已创建SQL> grant select on v_$sesstat toplustrace; 授权成功。

SQL> grant select on v_$statname to plustrace;授权成功。

SQL> grant select on v_$session to plustrace;授权成功。

SQL> grant plustrace to dba with admin option;授权成功。

SQL> set echo offSQL> grant plustrace to public;授权成功。

SQL> conn scott/tiger已连接。

SQL> set autotrace onSQL> select ename,sal from emp;ENAME SALSMITH 800ALLEN 1600WARD 1250JONES 2975TABLE ACCESS (FULL) OF 'EMP'StatisticsBLAKE2850 CLARK2450 KING5000 TURNER1500 JAMES950 FORD3000 MILLER1300已选择 12 行。

性能优化

性能优化

ORACLE 性能优化培训教材第一章数据库优化简介 (2)1.1数据库优化概念 (2)1.2数据库优化需要注意的问题 (2)第二章数据库优化内容 (3)2.1自顶向下的优化步骤 (3)2.2数据库内存优化 (5)2.3数据库的IO优化。

(6)2.4数据库SQL与访问路径方面的优化 (7)2.5开发环节与SQL优化 (7)第三章数据库SQL及访问路径优化 (7)3.1关于数据库优化器 (7)3.2优化器RBO,CBO优化方式介绍 (8)3.3关于数据库的统计信息 (8)3.4关于数据库的统计信息 (10)3.5关于数据库的执行计划 (11)3.6SQL语句中常用的HINT (14)3.7数据库中的等待事件 (15)3.8一些重要等待事件 (15)3.9一些优化工具的介绍 (17)3.10索引优化介绍 (18)3.11数据库分区技术 (19)3.12数据库分区上的索引问题 (21)3.13数据库SQL优化步骤 (22)3.13一个具体的优化SQL语句的例子 (22)3.14物化视图 (24)3.15资源管理器 (25)第4章本院HIS系统数据库存在问题及建议 (26)4.1优化前后AWR报告中的对比。

(26)4.2关于rac环境下序列的使用 (29)4.3随意在索引字段上使用函数的问题 (30)4.4 关于绑定变量问题 (33)4.4关于数据库分区问题 (34)4.5关于索引的问题, (35)第一章 数据库优化简介1.1数据库优化概念1)优化是有目的的更改系统的一个或多个组件,使其满足一个或多个目标的过程。

2)对ORACLE来说,优化是进行有目的的调整以改善性能,包括增加吞吐量,减少响应时间的过程1.2数据库优化需要注意的问题1) 优化要预先定义目标定义目标包括寻找当前系统的瓶颈,结合业务需求,设定优化目标值,该目标值应可量化,可衡量2) 需要了解不同应用系统类型的不同优化方法。

主要是针对OLTP 应用和DSS应用的不同优化方法。

2024年度Oracle的性能优化培训课件

2024年度Oracle的性能优化培训课件
监听器和网络配置
合理配置监听器参数和网络参 数,以优化客户端与数据库服 务器之间的通信性能和稳定性

18
05
CATALOGUE
Oracle SQL语句优化
2024/2/2
19
SQL语句编写规范
使用标准的SQL语法
遵循Oracle SQL的编写规范, 确保语句的准确性和可读性。
避免使用SELECT *
规范化与反规范化设计
01
通过数据库表的规范化,消除数据冗余;在必要时,通过反规
范化提高查询性能。
分区表设计
02
根据业务需求,将大表拆分为多个小表,提高查询和维护性能

视图与物化视图
03
利用视图简化复杂查询,物化视图缓存查询结果,提高查询速
度。
12
物理结构优化策略
2024/2/2
存储参数调整
根据数据访问特点,调整数据块大小、表空间管理方式等存储参 数。
2024/2/2
3
性能优化目标与意义
2024/2/2
目标
提高系统响应速度、吞吐量,降 低资源消耗,确保系统稳定、高 效运行。
意义
对于企业级应用,性能优化能够 显著提升用户体验,降低运营成 本,增强系统可扩展性和可维护 性。
4
性能优化常见场景
索引优化
合理创建、调整索引,提高数 据检索效率。
内存优化
调整内存参数配置,提高系统 缓存命中率,减少磁盘I/O。
SQL查询优化
针对慢查询、低效查询进行优 化,提高查询速度。
2024/2/2
存储优化
优化数据存储结构、表空间管 理,提高I/O性能。
并发与锁优化
优化事务处理、锁机制,提高 系统并发处理能力。

oracleSQL优化培训(精华整理)PPT课件

oracleSQL优化培训(精华整理)PPT课件

| 0 | SELECT STATEMENT |
| 1 | 26 | 4 (25)| 00:00:01 |
| 1 | SORT AGGREGATE |
| 1 | 26 |
|
|
| 2 | NESTED LOOPS |
| 1 | 26 | 4 (25)| 00:00:01 |
| 3 | VIEW
| VW_NSO_1 | 199 | 2587 | 2 (0)| 00:00:01 |
理解表的连接
HASH JOIN:1
---------------------------------------------------------
----------
| Id | Operation
开发人员应具备的优化能力
•能写好SQL,不犯低级错误。 •能创建高效索引。 •理解应用对表中数据的读取方式。 •理解索引对性能的重要意义。 •能理解常见的执行计划。 •可进行适当的调优。 •具备优化意识,开发中能兼顾性能。
SQL编写中的低级错误
• 对列进行运算 • 对列使用函数 • 数据类型不一致导致列发生隐式转化 • 使用*查询所有字段,包含了业务不需要的字段 • 进行不必要的排序 • union 可用 union all 替换 • 使用不必要的distinct
使用多少内存?消耗多少CPU? • 若SQL的执行效率不符合预期,有能力对其进行
优化吗?
执行计划
•执行计划:优化器制定的SQL的执行步骤。 •同一个SQL,可以有多个执行计划,要选取最优的那个。 •查询优化的目标:就是让优化器为SQL尽量生成最优的执行计划,使查 询的总开销(IO、CPU、网络传输等)最小。 •set autotrace、explain plan、dbms_xplan等。 •PL/SQL developer 中 使用F5快捷键

(O管理)ORACLESL性能优化(内部培训资料)(品质)

(O管理)ORACLESL性能优化(内部培训资料)(品质)

(O管理)ORACLESL性能优化(内部培训资料)ORACLESQL性能优化系列(一)1.选用适合的ORACLE优化器ORACLE的优化器共有3种:a.RULE(基于规则)b.COST(基于成本)c.CHOOSE(选择性)设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS.你当然也在SQL句级或是会话(session)级对其进行覆盖.为了使用基于成本的优化器(CBO,Cost-BasedOptimizer),你必须经常运行analyze命令,以增加数据库中的对象统计信息(objectstatistics)的准确性.如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关.如果table已经被analyze过,优化器模式将自动成为CBO,反之,数据库将采用RULE形式的优化器.在缺省情况下,ORACLE采用CHOOSE优化器,为了避免那些不必要的全表扫描(fulltablescan),你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器.2.访问Table的方式ORACLE采用两种访问表中记录的方式:a.全表扫描全表扫描就是顺序地访问表中每条记录.ORACLE采用一次读入多个数据块(databaseblock)的方式优化全表扫描.b.通过ROWID访问表你可以采用基于ROWID的访问方式情况,提高访问表的效率,,ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系.通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高.3.共享SQL语句为了不重复解析相同的SQL语句,在第一次解析之后,ORACLE将SQL语句存放在内存中.这块位于系统全局区域SGA(systemglobalarea)的共享池(sharedbufferpool)中的内存可以被所有的数据库用户共享.因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同,ORACLE就能很快获得已经被解析的语句以及最好的执行路径.ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用.可惜的是ORACLE只对简单的表提供高速缓冲(cachebuffering),这个功能并不适用于多表连接查询.数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了.当你向ORACLE提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,换行等).共享的语句必须满足三个条件:A.字符级的比较:当前被执行的语句和共享池中的语句必须完全相同.例如:SELECT*FROMEMP;和下列每一个都不同SELECT*fromEMP;Select*FromEmp;SELECT*FROMEMP;B.两个语句所指的对象必须完全相同: 例如:用户对象名如何访问Jacksal_limitprivatesynonym Work_citypublicsynonymPlant_detailpublicsynonym Jillsal_limitprivatesynonym Work_citypublicsynonymPlant_detailtableowner考虑一下下列SQL语句能否在这两个用户之间共享.SQL能否共享/原因selectmax(sal_cap)fromsal_limit;不能每个用户都有一个privatesynonym-sal_limit,它们是不同的对象selectcount(*0fromwork_citywheresdesclike'NEW%';能两个用户访问相同的对象publicsynonym-work_cityselecta.sdesc,b.locationfromwork_citya,plant_detailbwherea.city_id=b.city_id 不能用户jack通过privatesynonym访问plant_detail而jill是表的所有者,对象不同.C.两个SQL语句中必须使用相同的名字的绑定变量(bindvariables)例如:第一组的两个SQL语句是相同的(可以共享),而第二组中的两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值)a.selectpin,namefrompeoplewherepin=:blk1.pin;selectpin,namefrompeoplewherepin=:blk1.pin;b.selectpin,namefrompeoplewherepin=:blk1.ot_ind;selectpin,namefrompeoplewherepin=:blk1.ov_ind;4.选择最有效率的表名顺序(只在基于规则的优化器中有效)ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表drivingtable)将被最先处理.在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时,会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.例如:表TAB116,384条记录表TAB21条记录选择TAB2作为基础表(最好的方法)selectcount(*)fromtab1,tab2执行时间0.96秒选择TAB2作为基础表(不佳的方法)selectcount(*)fromtab2,tab1执行时间26.09秒如果有3个以上的表连接查询,那就需要选择交叉表(intersectiontable)作为基础表,交叉表是指那个被其他表所引用的表.例如:EMP表描述了LOCATION表和CATEGORY表的交集.SELECT*FROMLOCATIONL,CATEGORYC,EMPEWHEREE.EMP_NOBETWEEN1000AND2000 ANDE.CAT_NO=C.CAT_NOANDE.LOCN=L.LOCN将比下列SQL更有效率SELECT*FROMEMPE,LOCATIONL,CATEGORYCWHEREE.CAT_NO=C.CAT_NOANDE.LOCN=L.LOCNANDE.EMP_NOBETWEEN1000AND20005.WHERE子句中的连接顺序.ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.例如:(低效,执行时间156.3秒)SELECT…FROMEMPEWHERESAL>50000ANDJOB=‘MANAGER’AND25<(SELECTCOUNT(*)FROMEMP WHEREMGR=E.EMPNO);(高效,执行时间10.6秒)SELECT…FROMEMPEWHERE25<(SELECTCOUNT(*)FROMEMP WHEREMGR=E.EMPNO)ANDSAL>50000ANDJOB=‘MANAGER’;6.SELECT子句中避免使用‘*‘当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用‘*’是一个方便的方法.不幸的是,这是一个非常低效的方法.实际上,ORACLE在解析的过程中,会将’*’依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间.7.减少访问数据库的次数当执行每条SQL语句时,ORACLE在内部执行了许多工作:解析SQL语句,估算索引的利用率,绑定变量,读数据块等等.由此可见,减少访问数据库的次数,就能实际上减少ORACLE的工作量.例如,以下有三种方法可以检索出雇员号等于0342或0291的职员.方法1(最低效)SELECTEMP_NAME,SALARY,GRADEFROMEMPWHEREEMP_NO=342; SELECTEMP_NAME,SALARY,GRADE FROMEMPWHEREEMP_NO=291;方法2(次低效)DECLARECURSORC1(E_NONUMBER)IS SELECTEMP_NAME,SALARY,GRADE FROMEMPWHEREEMP_NO=E_NO;BEGINOPENC1(342);FETCHC1INTO…,..,..;…..OPENC1(291);FETCHC1INTO…,..,..;CLOSEC1;END;方法3(高效)SELECTA.EMP_NAME,A.SALARY,A.GRADE, B.EMP_NAME,B.SALARY,B.GRADE FROMEMPA,EMPBWHEREA.EMP_NO=342ANDB.EMP_NO=291;注意:在SQL*Plus,SQL*Forms和Pro*C中重新设置ARRAYSIZE参数,可以增加每次数据库访问的检索数据量,建议值为200ORACLESQL性能优化系列(三)8.使用DECODE函数来减少处理时间使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.例如:SELECTCOUNT(*),SUM(SAL)FROMEMPWHEREDEPT_NO=0020ANDENAMELIKE‘SMITH%’;SELECTCOUNT(*),SUM(SAL)FROMEMPWHEREDEPT_NO=0030ANDENAMELIKE‘SMITH%’;你可以用DECODE函数高效地得到相同结果SELECTCOUNT(DECODE(DEPT_NO,0020,’X’,NULL))D0020_COUNT, COUNT(DECODE(DEPT_NO,0030,’X’,NULL))D0030_COUNT, SUM(DECODE(DEPT_NO,0020,SAL,NULL))D0020_SAL,SUM(DECODE(DEPT_NO,0030,SAL,NULL))D0030_SAL FROMEMPWHEREENAMELIKE‘SMITH%’;类似的,DECODE函数也可以运用于GROUPBY和ORDERBY子句中.9.整合简单,无关联的数据库访问如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)例如:SELECTNAMEFROMEMPWHEREEMP_NO=1234;SELECTNAMEFROMDPTWHEREDPT_NO=10;SELECTNAMEFROMCATWHERECAT_TYPE=‘RD’;上面的3个查询可以被合并成一个:,,FROMCATC,DPTD,EMPE,DUALXWHERENVL(‘X’,X.DUMMY)=NVL(‘X’,E.ROWID(+)) ANDNVL(‘X’,X.DUMMY)=NVL(‘X’,D.ROWID(+)) ANDNVL(‘X’,X.DUMMY)=NVL(‘X’,C.ROWID(+)) ANDE.EMP_NO(+)=1234ANDD.DEPT_NO(+)=10ANDC.CAT_TYPE(+)=‘RD’;(译者按:虽然采取这种方法,效率得到提高,但是程序的可读性大大降低,所以读者还是要权衡之间的利弊)10.删除重复记录最高效的删除重复记录方法(因为使用了ROWID)DELETEFROMEMPEWHEREE.ROWID>(SELECTMIN(X.ROWID)FROMEMPXWHEREX.EMP_NO=E.EMP_NO);12.尽量多使用COMMIT只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:COMMIT所释放的资源:a.回滚段上用于恢复数据的信息.b.被程序语句获得的锁c.redologbuffer中的空间d.ORACLE为管理上述3种资源中的内部花费(译者按:在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼)ORACLESQL性能优化系列(四)13.计算记录条数和一般的观点相反,count(*)比count(1)稍快,当然如果可以通过索引检索,对索引列的计数仍旧是最快的.例如COUNT(EMPNO)(译者按:在CSDN论坛中,曾经对此有过相当热烈的讨论,作者的观点并不十分准确,通过实际的测试,上述三种方法并没有显著的性能差别)14.用Where子句替换HAVING子句避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤.这个处理需要排序,总计等操作.如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.例如:低效:SELECTREGION,AVG(LOG_SIZE)FROMLOCATIONGROUPBYREGIONHAVINGREGIONREGI ON!=‘SYDNEY’ANDREGION!=‘PERTH’高效SELECTREGION,AVG(LOG_SIZE)FROMLOCATIONWHEREREGIONREGION!=‘SYDNEY’ANDREGION!=‘PERTH’GROUPBYREGION(译者按:HAVING中的条件一般用于对一些集合函数的比较,如COUNT()等等.除此而外,一般的条件应该写在WHERE子句中)15.减少对表的查询在含有子查询的SQL语句中,要特别注意减少对表的查询.例如:低效SELECTTAB_NAMEFROMTABLESWHERETAB_NAME=(SELECTTAB_NAME FROMTAB_COLUMNS WHEREVERSION=604)ANDDB_VER=(SELECTDB_VER FROMTAB_COLUMNS WHEREVERSION=604)高效SELECTTAB_NAME FROMTABLESWHERE(TAB_NAME,DB_VER)=(SELECTTAB_NAME,DB_VER)FROMTAB_COLUMNSWHEREVERSION=604)Update多个Column例子:低效:UPDATEEMPSETEMP_CAT=(SELECTMAX(CATEGORY)FROMEMP_CATEGORIES), SAL_RANGE=(SELECTMAX(SAL_RANGE)FROMEMP_CATEGORIES) WHEREEMP_DEPT=0020;高效:UPDATEEMPSET(EMP_CAT,SAL_RANGE)=(SELECTMAX(CATEGORY),MAX(SAL_RANGE)FROMEMP_CATEGORIES)WHEREEMP_DEPT=0020;16.通过内部函数提高SQL效率.SELECTH.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC,COUNT(*) FROMHISTORY_TYPET,EMPE,EMP_HISTORYHWHEREH.EMPNO=E.EMPNOANDH.HIST_TYPE=T.HIST_TYPEGROUPBYH.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC;通过调用下面的函数可以提高效率.FUNCTIONLOOKUP_HIST_TYPE(TYPINNUMBER)RETURNVARCHAR2 ASTDESCVARCHAR2(30);CURSORC1ISSELECTTYPE_DESCFROMHISTORY_TYPEWHEREHIST_TYPE=TYP;BEGINOPENC1;FETCHC1INTOTDESC;CLOSEC1;RETURN(NVL(TDESC,’?’));END;FUNCTIONLOOKUP_EMP(EMPINNUMBER)RETURNVARCHAR2 ASENAMEVARCHAR2(30);CURSORC1ISSELECTENAMEFROMEMPWHEREEMPNO=EMP;BEGINOPENC1;FETCHC1INTOENAME;CLOSEC1;RETURN(NVL(ENAME,’?’));END;SELECTH.EMPNO,LOOKUP_EMP(H.EMPNO),H.HIST_TYPE,LOOKUP_HIST_TYPE(H.HIST_TYPE),COUNT(*) FROMEMP_HISTORYHGROUPBYH.EMPNO,H.HIST_TYPE;ORACLESQL性能优化系列(六)20.用表连接替换EXISTS通常来说,采用表连接的方式比EXISTS更有效率SELECTENAME FROMEMPE WHEREEXISTS(SELECT‘X’FROMDEPTWHEREDEPT_NO=E.DEPT_NO ANDDEPT_CAT=‘A’);(更高效)SELECTENAME FROMDEPTD,EMPE WHEREE.DEPT_NO=D.DEPT_NO ANDDEPT_CAT=‘A’;21.用EXISTS替换DISTINCT当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT.一般可以考虑用EXIST替换例如:低效:SELECTDISTINCTDEPT_NO,DEPT_NAMEFROMDEPTD,EMPEWHERED.DEPT_NO=E.DEPT_NO高效:SELECTDEPT_NO,DEPT_NAMEFROMDEPTDWHEREEXISTS(SELECT‘X’FROMEMPEWHEREE.DEPT_NO=D.DEPT_NO);EXISTS使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.22.识别’低效执行’的SQL语句用下列SQL工具找出低效SQL:SELECTEXECUTIONS,DISK_READS,BUFFER_GETS,ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2)Hit_radio,ROUND(DISK_READS/EXECUTIONS,2)Reads_per_run,SQL_TEXTFROMV$SQLAREAWHEREEXECUTIONS>0ANDBUFFER_GETS>0AND(BUFFER_GETS-DISK_READS)/BUFFER_GETS<0.8ORDERBY4DESC;(译者按:虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法)23.使用TKPROF工具来查询SQL性能状态SQLtrace工具收集正在执行的SQL的性能状态数据并记录到一个跟踪文件中.这个跟踪文件提供了许多有用的信息,例如解析次数.执行次数,CPU使用时间等.这些数据将可以用来优化你的系统.设置SQLTRACE在会话级别:有效ALTERSESSIONSETSQL_TRACETRUE设置SQLTRACE在整个数据库有效仿,你必须将SQL_TRACE参数在init.ora中设为TRUE,USER_DUMP_DEST参数说明了生成跟踪文件的目录ORACLESQL性能优化系列(七)24.用EXPLAINPLAN分析SQL语句EXPLAINPLAN是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句.通过分析,我们就可以知道ORACLE是怎么样连接表,使用什么方式扫描表(索引扫描或全表扫描)以及使用到的索引名称.你需要按照从里到外,从上到下的次序解读分析的结果.EXPLAINPLAN分析的结果是用缩进的格式排列的,最内部的操作将被最先解读,如果两个操作处于同一层中,带有最小操作号的将被首先执行.NESTEDLOOP是少数不按照上述规则处理的操作,正确的执行路径是检查对NESTEDLOOP提供数据的操作,其中操作号最小的将被最先处理.译者按:通过实践,感到还是用SQLPLUS中的SETTRACE功能比较方便.举例:SQL>list1SELECT*2FROMdept,emp3*WHEREemp.deptno=dept.deptnoSQL>setautotraceonexp;/*traceonly可以不显示执行结果*/ 或者SQL>setautotracetraceonlyexp;SQL>/14rowsselected.ExecutionPlan----------------------------------------------------------0SELECTSTATEMENTOptimizer=CHOOSE10NESTEDLOOPS21TABLEACCESS(FULL)OF'EMP'31TABLEACCESS(BYINDEXROWID)OF'DEPT'43INDEX(UNIQUESCAN)OF'PK_DEPT'(UNIQUE) Statistics---------------------------------------------------------- 0recursivecalls2dbblockgets30consistentgets0physicalreads0redosize2598bytessentviaSQL*Nettoclient503bytesreceivedviaSQL*Netfromclient2SQL*Netroundtripsto/fromclient0sorts(memory)0sorts(disk)14rowsprocessed通过以上分析,可以得出实际的执行步骤是:1.TABLEACCESS(FULL)OF'EMP'2.INDEX(UNIQUESCAN)OF'PK_DEPT'(UNIQUE)3.TABLEACCESS(BYINDEXROWID)OF'DEPT'4.NESTEDLOOPS(JOINING1AND3)ORACLESQL性能优化系列(八)25.用索引提高效率索引是表的一个概念部分,用来提高检索数据的效率.实际上,ORACLE使用了一个复杂的自平衡B-tree结构.通常,通过索引查询数据比全表扫描要快.当ORACLE找出执行查询和Update语句的最佳路径时,ORACLE优化器将使用索引.同样在联结多个表时使用索引也可以提高效率.另一个使用索引的好处是,它提供了主键(primarykey)的唯一性验证.除了那些LONG或LONGRAW数据类型,你可以索引几乎所有的列.通常,在大型表中使用索引特别有效.当然,你也会发现,在扫描小表时,使用索引同样能提高效率.虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价.索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时,索引本身也会被修改.这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5次的磁盘I/O.因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.译者按:定期的重构索引是有必要的.ALTERINDEX<INDEXNAME>REBUILD<TABLESPACENAME>26.索引的操作ORACLE对索引有两种访问模式.索引唯一扫描(INDEXUNIQUESCAN)大多数情况下,优化器通过WHERE子句访问INDEX.例如:表LODGING有两个索引:建立在LODGING列上的唯一性索引LODGING_PK和建立在MANAGER列上的非唯一性索引LODGING$MANAGER.SELECT*FROMLODGINGWHERELODGING=‘ROSEHILL’;在内部,上述SQL将被分成两步执行,首先,LODGING_PK索引将通过索引唯一扫描的方式被访问,获得相对应的ROWID,通过ROWID访问表的方式执行下一步检索.如果被检索返回的列包括在INDEX列中,ORACLE将不执行第二步的处理(通过ROWID访问表).因为检索数据保存在索引中,单单访问索引就可以完全满足查询结果.下面SQL只需要INDEXUNIQUESCAN操作.SELECTLODGINGFROMLODGINGWHERELODGING=‘ROSEHILL’;索引范围查询(INDEXRANGESCAN)适用于两种情况:1.基于一个范围的检索2.基于非唯一性索引的检索例1:SELECTLODGINGFROMLODGINGWHERELODGINGLIKE‘M%’;WHERE子句条件包括一系列值,ORACLE将通过索引范围查询的方式查询LODGING_PK.由于索引范围查询将返回一组值,它的效率就要比索引唯一扫描低一些.例2:SELECTLODGINGFROMLODGINGWHEREMANAGER=‘BILLGATES’;这个SQL的执行分两步,LODGING$MANAGER的索引范围查询(得到所有符合条件记录的ROWID)和下一步同过ROWID访问表得到LODGING列的值.由于LODGING$MANAGER 是一个非唯一性的索引,数据库不能对它执行索引唯一扫描.由于SQL返回LODGING列,而它并不存在于LODGING$MANAGER索引中,所以在索引范围查询后会执行一个通过ROWID访问表的操作.WHERE子句中,如果索引列所对应的值的第一个字符由通配符(WILDCARD)开始,索引将不被采用.SELECTLODGINGFROMLODGINGWHEREMANAGERLIKE‘%HANMAN’;在这种情况下,ORACLE将使用全表扫描.ORACLESQL性能优化系列(九)27.基础表的选择基础表(DrivingTable)是指被最先访问的表(通常以全表扫描的方式被访问).根据优化器的不同,SQL语句中基础表的选择是不一样的.如果你使用的是CBO(COSTBASEDOPTIMIZER),优化器会检查SQL语句中的每个表的物理大小,索引的状态,然后选用花费最低的执行路径.如果你用RBO(RULEBASEDOPTIMIZER),并且所有的连接条件都有索引对应,在这种情况下,基础表就是FROM子句中列在最后的那个表.举例:,B.MANAGERFROMWORKERA,LODGINGBWHEREA.LODGING=B.LODING;由于LODGING表的LODING列上有一个索引,而且WORKER表中没有相比较的索引,WORKER表将被作为查询中的基础表.28.多个平等的索引当SQL语句的执行路径可以使用分布在多个表上的多个索引时,ORACLE会同时使用多个索引并在运行时对它们的记录进行合并,检索出仅对全部索引有效的记录.在ORACLE选择执行路径时,唯一性索引的等级高于非唯一性索引.然而这个规则只有当WHERE子句中索引列和常量比较才有效.如果索引列和其他表的索引类相比较.这种子句在优化器中的等级是非常低的.如果不同表中两个想同等级的索引将被引用,FROM子句中表的顺序将决定哪个会被率先使用.FROM子句中最后的表的索引将有最高的优先级.如果相同表中两个想同等级的索引将被引用,WHERE子句中最先被引用的索引将有最高的优先级.举例:DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引.SELECTENAME,FROMEMPWHEREDEPT_NO=20ANDEMP_CAT=‘A’;这里,DEPTNO索引将被最先检索,然后同EMP_CAT索引检索出的记录进行合并.执行路径如下:TABLEACCESSBYROWIDONEMPAND-EQUALINDEXRANGESCANONDEPT_IDXINDEXRANGESCANONCAT_IDX29.等式比较和范围比较当WHERE子句中有索引列,ORACLE不能合并它们,ORACLE将用范围比较.举例:DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引.SELECTENAMEFROMEMPWHEREDEPTNO>20ANDEMP_CAT=‘A’;这里只有EMP_CAT索引被用到,然后所有的记录将逐条与DEPTNO条件进行比较.执行路径如下:TABLEACCESSBYROWIDONEMPINDEXRANGESCANONCAT_IDX30.不明确的索引等级当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最前面的.举例:DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引.SELECTENAMEFROMEMPWHEREDEPTNO>20ANDEMP_CAT>‘A’;这里,ORACLE只用到了DEPT_NO索引.执行路径如下: TABLEACCESSBYROWIDONEMPINDEXRANGESCANONDEPT_IDX译者按:我们来试一下以下这种情况:SQL>selectindex_name,uniquenessfromuser_indexeswheretable_name='EMP'; INDEX_NAMEUNIQUENES---------------------------------------EMPNOUNIQUEEMPTYPENONUNIQUESQL>select*fromempwhereempno>=2andemp_type='A';norowsselectedExecutionPlan----------------------------------------------------------0SELECTSTATEMENTOptimizer=CHOOSE10TABLEACCESS(BYINDEXROWID)OF'EMP'21INDEX(RANGESCAN)OF'EMPTYPE'(NON-UNIQUE)虽然EMPNO是唯一性索引,但是由于它所做的是范围比较,等级要比非唯一性索引的等式比较低!ORACLESQL性能优化系列(十)31.强制索引失效如果两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少).举例:SELECTENAMEFROMEMPWHEREEMPNO=7935ANDDEPTNO+0=10/*DEPTNO上的索引将失效*/ANDEMP_TYPE||‘’=‘A’/*EMP_TYPE上的索引将失效*/这是一种相当直接的提高查询效率的办法.但是你必须谨慎考虑这种策略,一般来说,只有在你希望单独优化几个SQL时才能采用它.这里有一个例子关于何时采用这种策略,假设在EMP表的EMP_TYPE列上有一个非唯一性的索引而EMP_CLASS上没有索引.SELECTENAMEFROMEMPWHEREEMP_TYPE=‘A’ANDEMP_CLASS=‘X’;优化器会注意到EMP_TYPE上的索引并使用它.这是目前唯一的选择.如果,一段时间以后,另一个非唯一性建立在EMP_CLASS上,优化器必须对两个索引进行选择,在通常情况下,优化器将使用两个索引并在他们的结果集合上执行排序及合并.然而,如果其中一个索引(EMP_TYPE)接近于唯一性而另一个索引(EMP_CLASS)上有几千个重复的值.排序及合并就会成为一种不必要的负担.在这种情况下,你希望使优化器屏蔽掉EMP_CLASS索引. 用下面的方案就可以解决问题.SELECTENAMEFROMEMPWHEREEMP_TYPE=‘A’ANDEMP_CLASS||’’=‘X’;32.避免在索引列上使用计算.WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.举例:低效:SELECT…FROMDEPTWHERESAL*12>25000;高效:。

ORACLE SQL性能优化(全)

ORACLE SQL性能优化(全)

SQL语句的处理过程
绑定(BIND): 1. 在语句中查找绑定变量 2. ቤተ መጻሕፍቲ ባይዱ值(或重新赋值)
SQL语句的处理过程
执行(EXECUTE): 1. 应用执行计划 2. 执行必要的I/O和排序操作
提取(FETCH): 1. 从查询结果中返回记录 2. 必要时进行排序 3. 使用ARRAY FETCH机制
共享游标:好处
1. 减少解析 2. 动态内存调整 3. 提高内存使用率
书写可共享的SQL
绑定变量和共享游标
ORACLE 优化器模式 概述
Oracle的优化器共有3种模式:RULE (基于规则)、COST (基于成本)、CHOOSE(基于选择)。
设置缺省的优化器的方法,是在启动参数文件中针对 OPTIMIZER_ MODE参数的各种声明进行选择,如RULE、COST、 CHOOSE、ALL_ ROWS、FIRST_ ROWS。当然也可以在SQL语 句级别或是会话级别对其进行覆盖。
SQL Tunning 的重点
SQL: insert, update, delete, select; 主要关注的是select 关注的是:如何用最小的硬件资源消
耗、最少的响应时间定位数据位置
SQL优化的一般性原则
目标: 减少服务器资源消耗(主要是磁盘IO);
设计方面: 尽量依赖oracle的优化器,并为其提供条件; 合适的索引,索引的双重效应,列的选择性;
绑定变量解决重编译问题
未使用绑定变量的语句
sprintf(sqlstr, "insert into scott.test1 (num1, num2) values (%d,%d)",n_var1, n_var2);
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

(O管理)ORACLESL性能优化(内部培训资料)ORACLESQL性能优化系列(一)1.选用适合的ORACLE优化器ORACLE的优化器共有3种:a.RULE(基于规则)b.COST(基于成本)c.CHOOSE(选择性)设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS.你当然也在SQL句级或是会话(session)级对其进行覆盖.为了使用基于成本的优化器(CBO,Cost-BasedOptimizer),你必须经常运行analyze命令,以增加数据库中的对象统计信息(objectstatistics)的准确性.如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关.如果table已经被analyze过,优化器模式将自动成为CBO,反之,数据库将采用RULE形式的优化器.在缺省情况下,ORACLE采用CHOOSE优化器,为了避免那些不必要的全表扫描(fulltablescan),你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器.2.访问Table的方式ORACLE采用两种访问表中记录的方式:a.全表扫描全表扫描就是顺序地访问表中每条记录.ORACLE采用一次读入多个数据块(databaseblock)的方式优化全表扫描.b.通过ROWID访问表你可以采用基于ROWID的访问方式情况,提高访问表的效率,,ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系.通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高.3.共享SQL语句为了不重复解析相同的SQL语句,在第一次解析之后,ORACLE将SQL语句存放在内存中.这块位于系统全局区域SGA(systemglobalarea)的共享池(sharedbufferpool)中的内存可以被所有的数据库用户共享.因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同,ORACLE就能很快获得已经被解析的语句以及最好的执行路径.ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用.可惜的是ORACLE只对简单的表提供高速缓冲(cachebuffering),这个功能并不适用于多表连接查询.数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了.当你向ORACLE提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,换行等).共享的语句必须满足三个条件:A.字符级的比较:当前被执行的语句和共享池中的语句必须完全相同.例如:SELECT*FROMEMP;和下列每一个都不同SELECT*fromEMP;Select*FromEmp;SELECT*FROMEMP;B.两个语句所指的对象必须完全相同: 例如:用户对象名如何访问Jacksal_limitprivatesynonym Work_citypublicsynonymPlant_detailpublicsynonym Jillsal_limitprivatesynonym Work_citypublicsynonymPlant_detailtableowner考虑一下下列SQL语句能否在这两个用户之间共享.SQL能否共享/原因selectmax(sal_cap)fromsal_limit;不能每个用户都有一个privatesynonym-sal_limit,它们是不同的对象selectcount(*0fromwork_citywheresdesclike'NEW%';能两个用户访问相同的对象publicsynonym-work_cityselecta.sdesc,b.locationfromwork_citya,plant_detailbwherea.city_id=b.city_id 不能用户jack通过privatesynonym访问plant_detail而jill是表的所有者,对象不同.C.两个SQL语句中必须使用相同的名字的绑定变量(bindvariables)例如:第一组的两个SQL语句是相同的(可以共享),而第二组中的两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值)a.selectpin,namefrompeoplewherepin=:blk1.pin;selectpin,namefrompeoplewherepin=:blk1.pin;b.selectpin,namefrompeoplewherepin=:blk1.ot_ind;selectpin,namefrompeoplewherepin=:blk1.ov_ind;4.选择最有效率的表名顺序(只在基于规则的优化器中有效)ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表drivingtable)将被最先处理.在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时,会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.例如:表TAB116,384条记录表TAB21条记录选择TAB2作为基础表(最好的方法)selectcount(*)fromtab1,tab2执行时间0.96秒选择TAB2作为基础表(不佳的方法)selectcount(*)fromtab2,tab1执行时间26.09秒如果有3个以上的表连接查询,那就需要选择交叉表(intersectiontable)作为基础表,交叉表是指那个被其他表所引用的表.例如:EMP表描述了LOCATION表和CATEGORY表的交集.SELECT*FROMLOCATIONL,CATEGORYC,EMPEWHEREE.EMP_NOBETWEEN1000AND2000 ANDE.CAT_NO=C.CAT_NOANDE.LOCN=L.LOCN将比下列SQL更有效率SELECT*FROMEMPE,LOCATIONL,CATEGORYCWHEREE.CAT_NO=C.CAT_NOANDE.LOCN=L.LOCNANDE.EMP_NOBETWEEN1000AND20005.WHERE子句中的连接顺序.ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.例如:(低效,执行时间156.3秒)SELECT…FROMEMPEWHERESAL>50000ANDJOB=‘MANAGER’AND25<(SELECTCOUNT(*)FROMEMP WHEREMGR=E.EMPNO);(高效,执行时间10.6秒)SELECT…FROMEMPEWHERE25<(SELECTCOUNT(*)FROMEMP WHEREMGR=E.EMPNO)ANDSAL>50000ANDJ OB=‘MANAGER’;6.SELECT子句中避免使用‘*‘当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用‘*’是一个方便的方法.不幸的是,这是一个非常低效的方法.实际上,ORACLE在解析的过程中,会将’*’依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间.7.减少访问数据库的次数当执行每条SQL语句时,ORACLE在内部执行了许多工作:解析SQL语句,估算索引的利用率,绑定变量,读数据块等等.由此可见,减少访问数据库的次数,就能实际上减少ORACLE的工作量.例如,以下有三种方法可以检索出雇员号等于0342或0291的职员.方法1(最低效)SELECTEMP_NAME,SALARY,GRADEFROMEMPWHEREEMP_NO=342; SELECTEMP_NAME,SALARY,GRADE FROMEMPWHEREEMP_NO=291;方法2(次低效)DECLARECURSORC1(E_NONUMBER)IS SELECTEMP_NAME,SALARY,GRADE FROMEMPWHEREEMP_NO=E_NO;BEGINOPENC1(342);FETCHC1INTO…,..,..;…..OPENC1(291);FETCHC1INTO…,..,..;CLOSEC1;END;方法3(高效)SELECTA.EMP_NAME,A.SALARY,A.GRADE, B.EMP_NAME,B.SALARY,B.GRADE FROMEMPA,EMPBWHEREA.EMP_NO=342ANDB.EMP_NO=291;注意:在SQL*Plus,SQL*Forms和Pro*C中重新设置ARRAYSIZE参数,可以增加每次数据库访问的检索数据量,建议值为200ORACLESQL性能优化系列(三)8.使用DECODE函数来减少处理时间使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.例如:SELECTCOUNT(*),SUM(SAL)FROMEMPWHEREDEPT_NO=0020ANDENAMELIKE‘SMITH%’;SELECTCOUNT(*),SUM(SAL)FROMEMPWHEREDEPT_NO=0030ANDENAMELIKE‘SMITH%’;你可以用DECODE函数高效地得到相同结果SELECTCOUNT(DECODE(DEPT_NO,0020,’X’,NULL))D0020_COUNT, COUNT(DECODE(DEPT_NO,0030,’X’,NULL))D0030_COUNT, SUM(DECODE(DEPT_NO,0020,SAL,NULL))D0020_SAL,SUM(DECODE(DEPT_NO,0030,SAL,NULL))D0030_SAL FROMEMPWHEREENAMELIKE‘SMITH%’;类似的,DECODE函数也可以运用于GROUPBY和ORDERBY子句中.9.整合简单,无关联的数据库访问如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)例如:SELECTNAMEFROMEMPWHEREEMP_NO=1234;SELECTNAMEFROMDPTWHEREDPT_NO=10;SELECTNAMEFROMCATWHERECAT_TYPE=‘RD’;上面的3个查询可以被合并成一个:,,FROMCATC,DPTD,EMPE,DUALXWHERENVL(‘X’,X.DUMMY)=NVL(‘X’,E.ROWID(+)) ANDNVL(‘X’,X.DUMMY)=NVL(‘X’,D.ROWID(+)) ANDNVL(‘X’,X.DUMMY)=NVL(‘X’,C.ROWID(+)) ANDE.EMP_NO(+)=1234ANDD.DEPT_NO(+)=10ANDC.CAT_TYP E(+)=‘RD’;(译者按:虽然采取这种方法,效率得到提高,但是程序的可读性大大降低,所以读者还是要权衡之间的利弊)10.删除重复记录最高效的删除重复记录方法(因为使用了ROWID)DELETEFROMEMPEWHEREE.ROWID>(SELECTMIN(X.ROWID)FROMEMPXWHEREX.EMP_NO=E.EMP_NO);12.尽量多使用COMMIT只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:COMMIT所释放的资源:a.回滚段上用于恢复数据的信息.b.被程序语句获得的锁c.redologbuffer中的空间d.ORACLE为管理上述3种资源中的内部花费(译者按:在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼)ORACLESQL性能优化系列(四)13.计算记录条数和一般的观点相反,count(*)比count(1)稍快,当然如果可以通过索引检索,对索引列的计数仍旧是最快的.例如COUNT(EMPNO)(译者按:在CSDN论坛中,曾经对此有过相当热烈的讨论,作者的观点并不十分准确,通过实际的测试,上述三种方法并没有显著的性能差别)14.用Where子句替换HAVING子句避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤.这个处理需要排序,总计等操作.如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.例如:低效:SELECTREGION,AVG(LOG_SIZE)FROMLOCATIONGROUPBYREGIONHAVINGREGIONRE GION!=‘SYDNEY’ANDREGION!=‘PERTH’高效SELECTREGION,AVG(LOG_SIZE)FROMLOCATIONWHEREREGIONREGION!=‘SYDNEY’ANDREGION!=‘PERTH’GROUPBYREGION(译者按:HAVING中的条件一般用于对一些集合函数的比较,如COUNT()等等.除此而外,一般的条件应该写在WHERE子句中)15.减少对表的查询在含有子查询的SQL语句中,要特别注意减少对表的查询.例如:低效SELECTTAB_NAMEFROMTABLESWHERETAB_NAME=(SELECTTAB_NAME FROMTAB_COLUMNS WHEREVERSION=604)ANDDB_VER=(SELECTDB_VER FROMTAB_COLUMNS WHEREVERSION=604)高效SELECTTAB_NAME FROMTABLESWHERE(TAB_NAME,DB_VER)=(SELECTTAB_NAME,DB_VER)FROMTAB_COLUMNSWHEREVERSION=604)Update多个Column例子:低效:UPDATEEMPSETEMP_CAT=(SELECTMAX(CATEGORY)FROMEMP_CATEGORIES), SAL_RANGE=(SELECTMAX(SAL_RANGE)FROMEMP_CATEGORIES) WHEREEMP_DEPT=0020;高效:UPDATEEMPSET(EMP_CAT,SAL_RANGE)=(SELECTMAX(CATEGORY),MAX(SAL_RANGE)FROMEMP_CATEGORIES)WHEREEMP_DEPT=0020;16.通过内部函数提高SQL效率.SELECTH.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC,COUNT(*) FROMHISTORY_TYPET,EMPE,EMP_HISTORYHWHEREH.EMPNO=E.EMPNOANDH.HIST_TYPE=T.HIST_TYPEGROUPBYH.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC;通过调用下面的函数可以提高效率.FUNCTIONLOOKUP_HIST_TYPE(TYPINNUMBER)RETURNVARCHAR2 ASTDESCVARCHAR2(30);CURSORC1ISSELECTTYPE_DESCFROMHISTORY_TYPEWHEREHIST_TYPE=TYP;BEGINOPENC1;FETCHC1INTOTDESC;CLOSEC1;RETURN(NVL(TDESC,’?’));END;FUNCTIONLOOKUP_EMP(EMPINNUMBER)RETURNVARCHAR2 ASENAMEVARCHAR2(30);CURSORC1ISSELECTENAMEFROMEMPWHEREEMPNO=EMP;BEGINOPENC1;FETCHC1INTOENAME;CLOSEC1;RETURN(NVL(ENAME,’?’));END;SELECTH.EMPNO,LOOKUP_EMP(H.EMPNO),H.HIST_TYPE,LOOKUP_HIST_TYPE(H.HIST_TYPE),COUNT(*) FROMEMP_HISTORYHGROUPBYH.EMPNO,H.HIST_TYPE;ORACLESQL性能优化系列(六)20.用表连接替换EXISTS通常来说,采用表连接的方式比EXISTS更有效率SELECTENAME FROMEMPE WHEREEXISTS(SELECT‘X’FROMDEPTWHEREDEPT_NO=E.DEPT_NO ANDDEPT_CAT=‘A’);(更高效)SELECTENAME FROMDEPTD,EMPE WHEREE.DEPT_NO=D.DEPT_NO ANDDEPT_CAT=‘A’;21.用EXISTS替换DISTINCT当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT.一般可以考虑用EXIST替换例如:低效:SELECTDISTINCTDEPT_NO,DEPT_NAMEFROMDEPTD,EMPEWHERED.DEPT_NO=E.DEPT_NO高效:SELECTDEPT_NO,DEPT_NAMEFROMDEPTDWHEREEXISTS(SELECT‘X’FROMEMPEWHEREE.DEPT_NO=D.DEPT_NO);EXISTS使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.22.识别’低效执行’的SQL语句用下列SQL工具找出低效SQL:SELECTEXECUTIONS,DISK_READS,BUFFER_GETS,ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2)Hit_radio,ROUND(DISK_READS/EXECUTIONS,2)Reads_per_run,SQL_TEXTFROMV$SQLAREAWHEREEXECUTIONS>0ANDBUFFER_GETS>0AND(BUFFER_GETS-DISK_READS)/BUFFER_GETS<0.8ORDERBY4DESC;(译者按:虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法)23.使用TKPROF工具来查询SQL性能状态SQLtrace工具收集正在执行的SQL的性能状态数据并记录到一个跟踪文件中.这个跟踪文件提供了许多有用的信息,例如解析次数.执行次数,CPU使用时间等.这些数据将可以用来优化你的系统.设置SQLTRACE在会话级别:有效ALTERSESSIONSETSQL_TRACETRUE设置SQLTRACE在整个数据库有效仿,你必须将SQL_TRACE参数在init.ora中设为TRUE,USER_DUMP_DEST参数说明了生成跟踪文件的目录ORACLESQL性能优化系列(七)24.用EXPLAINPLAN分析SQL语句EXPLAINPLAN是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句.通过分析,我们就可以知道ORACLE是怎么样连接表,使用什么方式扫描表(索引扫描或全表扫描)以及使用到的索引名称.你需要按照从里到外,从上到下的次序解读分析的结果.EXPLAINPLAN分析的结果是用缩进的格式排列的,最内部的操作将被最先解读,如果两个操作处于同一层中,带有最小操作号的将被首先执行.NESTEDLOOP是少数不按照上述规则处理的操作,正确的执行路径是检查对NESTEDLOOP提供数据的操作,其中操作号最小的将被最先处理.译者按:通过实践,感到还是用SQLPLUS中的SETTRACE功能比较方便.举例:SQL>list1SELECT*2FROMdept,emp3*WHEREemp.deptno=dept.deptnoSQL>setautotraceonexp;/*traceonly可以不显示执行结果*/ 或者SQL>setautotracetraceonlyexp;SQL>/14rowsselected.ExecutionPlan----------------------------------------------------------0SELECTSTATEMENTOptimizer=CHOOSE10NESTEDLOOPS21TABLEACCESS(FULL)OF'EMP'31TABLEACCESS(BYINDEXROWID)OF'DEPT'43INDEX(UNIQUESCAN)OF'PK_DEPT'(UNIQUE) Statistics---------------------------------------------------------- 0recursivecalls2dbblockgets30consistentgets0physicalreads0redosize2598bytessentviaSQL*Nettoclient503bytesreceivedviaSQL*Netfromclient2SQL*Netroundtripsto/fromclient0sorts(memory)0sorts(disk)14rowsprocessed通过以上分析,可以得出实际的执行步骤是:1.TABLEACCESS(FULL)OF'EMP'2.INDEX(UNIQUESCAN)OF'PK_DEPT'(UNIQUE)3.TABLEACCESS(BYINDEXROWID)OF'DEPT'4.NESTEDLOOPS(JOINING1AND3)ORACLESQL性能优化系列(八)25.用索引提高效率索引是表的一个概念部分,用来提高检索数据的效率.实际上,ORACLE使用了一个复杂的自平衡B-tree结构.通常,通过索引查询数据比全表扫描要快.当ORACLE找出执行查询和Update语句的最佳路径时,ORACLE优化器将使用索引.同样在联结多个表时使用索引也可以提高效率.另一个使用索引的好处是,它提供了主键(primarykey)的唯一性验证.除了那些LONG或LONGRAW数据类型,你可以索引几乎所有的列.通常,在大型表中使用索引特别有效.当然,你也会发现,在扫描小表时,使用索引同样能提高效率.虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价.索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时,索引本身也会被修改.这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5次的磁盘I/O.因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.译者按:定期的重构索引是有必要的.ALTERINDEX<INDEXNAME>REBUILD<TABLESPACENAME>26.索引的操作ORACLE对索引有两种访问模式.索引唯一扫描(INDEXUNIQUESCAN)大多数情况下,优化器通过WHERE子句访问INDEX.例如:表LODGING有两个索引:建立在LODGING列上的唯一性索引LODGING_PK和建立在MANAGER列上的非唯一性索引LODGING$MANAGER.SELECT*FROMLODGINGWHERELODGING=‘ROSEHILL’;在内部,上述SQL将被分成两步执行,首先,LODGING_PK索引将通过索引唯一扫描的方式被访问,获得相对应的ROWID,通过ROWID访问表的方式执行下一步检索.如果被检索返回的列包括在INDEX列中,ORACLE将不执行第二步的处理(通过ROWID访问表).因为检索数据保存在索引中,单单访问索引就可以完全满足查询结果.下面SQL只需要INDEXUNIQUESCAN操作.SELECTLODGINGFROMLODGINGWHERELODGING=‘ROSEHILL’;索引范围查询(INDEXRANGESCAN)适用于两种情况:1.基于一个范围的检索2.基于非唯一性索引的检索例1:SELECTLODGINGFROMLODGINGWHERELODGINGLIKE‘M%’;WHERE子句条件包括一系列值,ORACLE将通过索引范围查询的方式查询LODGING_PK.由于索引范围查询将返回一组值,它的效率就要比索引唯一扫描低一些.例2:SELECTLODGINGFROMLODGINGWHEREMANAGER=‘BILLGATES’;这个SQL的执行分两步,LODGING$MANAGER的索引范围查询(得到所有符合条件记录的ROWID)和下一步同过ROWID访问表得到LODGING列的值.由于LODGING$MANAGER 是一个非唯一性的索引,数据库不能对它执行索引唯一扫描.由于SQL返回LODGING列,而它并不存在于LODGING$MANAGER索引中,所以在索引范围查询后会执行一个通过ROWID访问表的操作.WHERE子句中,如果索引列所对应的值的第一个字符由通配符(WILDCARD)开始,索引将不被采用.SELECTLODGINGFROMLODGINGWHEREMANAGERLIKE‘%HANMAN’;在这种情况下,ORACLE将使用全表扫描.ORACLESQL性能优化系列(九)27.基础表的选择基础表(DrivingTable)是指被最先访问的表(通常以全表扫描的方式被访问).根据优化器的不同,SQL语句中基础表的选择是不一样的.如果你使用的是CBO(COSTBASEDOPTIMIZER),优化器会检查SQL语句中的每个表的物理大小,索引的状态,然后选用花费最低的执行路径.如果你用RBO(RULEBASEDOPTIMIZER),并且所有的连接条件都有索引对应,在这种情况下,基础表就是FROM子句中列在最后的那个表.举例:,B.MANAGERFROMWORKERA,LODGINGBWHEREA.LODGING=B.LODING;由于LODGING表的LODING列上有一个索引,而且WORKER表中没有相比较的索引,WORKER表将被作为查询中的基础表.28.多个平等的索引当SQL语句的执行路径可以使用分布在多个表上的多个索引时,ORACLE会同时使用多个索引并在运行时对它们的记录进行合并,检索出仅对全部索引有效的记录.在ORACLE选择执行路径时,唯一性索引的等级高于非唯一性索引.然而这个规则只有当WHERE子句中索引列和常量比较才有效.如果索引列和其他表的索引类相比较.这种子句在优化器中的等级是非常低的.如果不同表中两个想同等级的索引将被引用,FROM子句中表的顺序将决定哪个会被率先使用.FROM子句中最后的表的索引将有最高的优先级.如果相同表中两个想同等级的索引将被引用,WHERE子句中最先被引用的索引将有最高的优先级.举例:DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引.SELECTENAME,FROMEMPWHEREDEPT_NO=20ANDEMP_CAT=‘A’;这里,DEPTNO索引将被最先检索,然后同EMP_CAT索引检索出的记录进行合并.执行路径如下:TABLEACCESSBYROWIDONEMPAND-EQUALINDEXRANGESCANONDEPT_IDXINDEXRANGESCANONCAT_IDX29.等式比较和范围比较当WHERE子句中有索引列,ORACLE不能合并它们,ORACLE将用范围比较.举例:DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引.SELECTENAMEFROMEMPWHEREDEPTNO>20ANDEMP_CAT=‘A’;这里只有EMP_CAT索引被用到,然后所有的记录将逐条与DEPTNO条件进行比较.执行路径如下:TABLEACCESSBYROWIDONEMPINDEXRANGESCANONCAT_IDX30.不明确的索引等级当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最前面的.举例:DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引.SELECTENAMEFROMEMPWHEREDEPTNO>20ANDEMP_CAT>‘A’;这里,ORACLE只用到了DEPT_NO索引.执行路径如下: TABLEACCESSBYROWIDONEMPINDEXRANGESCANONDEPT_IDX译者按:我们来试一下以下这种情况:SQL>selectindex_name,uniquenessfromuser_indexeswheretable_name='EMP'; INDEX_NAMEUNIQUENES---------------------------------------EMPNOUNIQUEEMPTYPENONUNIQUESQL>select*fromempwhereempno>=2andemp_type='A';norowsselectedExecutionPlan----------------------------------------------------------0SELECTSTATEMENTOptimizer=CHOOSE10TABLEACCESS(BYINDEXROWID)OF'EMP'21INDEX(RANGESCAN)OF'EMPTYPE'(NON-UNIQUE)虽然EMPNO是唯一性索引,但是由于它所做的是范围比较,等级要比非唯一性索引的等式比较低!ORACLESQL性能优化系列(十)31.强制索引失效如果两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少).举例:SELECTENAMEFROMEMPWHEREEMPNO=7935ANDDEPTNO+0=10/*DEPTNO上的索引将失效*/ANDEMP_TYPE||‘’=‘A’/*EMP_TYPE上的索引将失效*/这是一种相当直接的提高查询效率的办法.但是你必须谨慎考虑这种策略,一般来说,只有在你希望单独优化几个SQL时才能采用它.这里有一个例子关于何时采用这种策略,假设在EMP表的EMP_TYPE列上有一个非唯一性的索引而EMP_CLASS上没有索引.SELECTENAMEFROMEMPWHEREEMP_TYPE=‘A’ANDEMP_CLASS=‘X’;优化器会注意到EMP_TYPE上的索引并使用它.这是目前唯一的选择.如果,一段时间以后,另一个非唯一性建立在EMP_CLASS上,优化器必须对两个索引进行选择,在通常情况下,优化器将使用两个索引并在他们的结果集合上执行排序及合并.然而,如果其中一个索引(EMP_TYPE)接近于唯一性而另一个索引(EMP_CLASS)上有几千个重复的值.排序及合并就会成为一种不必要的负担.在这种情况下,你希望使优化器屏蔽掉EMP_CLASS索引. 用下面的方案就可以解决问题.SELECTENAMEFROMEMPWHEREEMP_TYPE=‘A’ANDEMP_CLASS||’’=‘X’;32.避免在索引列上使用计算.WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.举例:低效:SELECT…FROMDEPTWHERESAL*12>25000;高效:。

相关文档
最新文档