




已阅读5页,还剩37页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ORACLESQL语句优化,资料共享,此内容参考:ORACLESQL性能优化系列.doc,访问Table的方式,ORACLE采用两种访问表中记录的方式:a.全表扫描全表扫描就是顺序地访问表中每条记录.ORACLE采用一次读入多个数据块(databaseblock)的方式优化全表扫描.b.通过ROWID访问表你可以采用基于ROWID的访问方式情况,提高访问表的效率,ROWID包含了表中记录的物理位置信息.ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系.通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高.,删除重复记录,最高效的删除重复记录方法(因为使用了ROWID)DELETEFROMEMPEWHEREE.ROWID(SELECTMIN(X.ROWID)FROMEMPXWHEREX.EMP_NO=E.EMP_NO);,基于索引的SQL语句优化,1.ISNULL与ISNOTNULL2.联接列3.带通配符(%)的like语句4.Orderby语句5.NOT6.IN和EXISTS7.用表连接替换EXISTS8.用EXISTS替换DISTINCT9.用WHERE替代ORDERBY10.用UNION替换OR(适用于索引列)11.用IN来替换OR,1.ISNULL与ISNOTNULL,不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用isnull或isnotnull的语句优化器是不允许使用索引的。,2.联接列,对于有联接的列,即使最后的联接值为一个静态值,优化器不会使用索引的。select*fromemployeewherefirst_name|last_name=GeorgeBush;使用索引的语句Select*Fromemployeewherefirst_name=Georgeandlast_name=Bush;select*fromemployeewherefirst_name=SUBSTR(,3.带通配符(%)的like语句,通配符(%)在搜寻词首出现,所以Oracle系统不使用的索引不使用索引的SQLselect*fromemployeewherelast_namelike%Bush%;使用索引的SQLselect*fromemployeewherelast_namelikec%;,4.Orderby语句,Orderby语句决定了Oracle如何将返回的查询结果排序。Orderby语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Orderby语句的非索引项或者有计算表达式都将降低查询速度。仔细检查orderby语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写orderby语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在orderby子句中使用表达式。,5.逻辑表达式NOT,不使用索引wherenot(status=VALID);wherestatusVALID;wherestatus!=VALID;select*fromemployeewheresalary3000;使用索引select*fromemployeewheresalary3000;,6.IN和EXISTS,.wherecolumnin(select*from.where.);.whereexists(selectXfrom.where.);通过使用EXISTS,Oracle系统会首先检查主查询,然后运行子查询直到找到第一个匹配项,这就节省了时间。Oracle系统在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因同时应尽可能使用NOTEXISTS来代替NOTIN,尽管二者都使用了NOT(不能使用索引而降低速度),但NOTEXISTS要比NOTIN查询效率更高,7.用表连接替换EXISTS,通常来说,采用表连接的方式比EXISTS更有效率SELECTENAMEFROMEMPEWHEREEXISTS(SELECTXFROMDEPTWHEREDEPT_NO=E.DEPT_NOANDDEPT_CAT=A);(更高效)SELECTENAMEFROMDEPTD,EMPEWHEREE.DEPT_NO=D.DEPT_NOANDDEPT_CAT=A;,8.用EXISTS替换DISTINCT,多表信息的查询时,避免在SELECT子句中使用DISTINCT.一般可以考虑用EXIST替换,例如:低效:SELECTDISTINCTDEPT_NO,DEPT_NAMEFROMDEPTD,EMPEWHERED.DEPT_NO=E.DEPT_NO高效:SELECTDEPT_NO,DEPT_NAMEFROMDEPTDWHEREEXISTS(SELECTXFROMEMPEWHEREE.DEPT_NO=D.DEPT_NO);EXISTS使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.,9.用WHERE替代ORDERBY,ORDERBY子句只在两种严格的条件下使用索引.ORDERBY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.ORDERBY中所有的列必须定义为非空.WHERE子句使用的索引和ORDERBY子句中所使用的索引不能并列.例如:表DEPT包含以下列:DEPT_CODEPKNOTNULLDEPT_DESCNOTNULLDEPT_TYPENULL非唯一性的索引(DEPT_TYPE),9.用WHERE替代ORDERBY,低效:(索引不被使用)SELECTDEPT_CODEFROMDEPTORDERBYDEPT_TYPEEXPLAINPLAN:SORTORDERBYTABLEACCESSFULL高效:(使用索引)SELECTDEPT_CODEFROMDEPTWHEREDEPT_TYPE0EXPLAINPLAN:TABLEACCESSBYROWIDONEMPINDEXRANGESCANONDEPT_IDX,10.用UNION替换OR(适用于索引列),通常情况下,用UNION替换WHERE子句中的OR将会起到较好的效果.对索引列使用OR将造成全表扫描.注意,以上规则只针对多个索引列有效.如果有column没有被索引,查询效率可能会因为你没有选择OR而降低.在下面的例子中,LOC_ID和REGION上都建有索引.高效:SELECTLOC_ID,LOC_DESC,REGIONFROMLOCATIONWHERELOC_ID=10UNIONSELECTLOC_ID,LOC_DESC,REGIONFROMLOCATIONWHEREREGION=“MELBOURNE”低效:SELECTLOC_ID,LOC_DESC,REGIONFROMLOCATIONWHERELOC_ID=10ORREGION=“MELBOURNE”,11.用IN来替换OR,下面的查询可以被更有效率的语句替换:低效:SELECT.FROMLOCATIONWHERELOC_ID=10ORLOC_ID=20ORLOC_ID=30高效SELECTFROMLOCATIONWHERELOC_ININ(10,20,30);,最有效率的表名顺序,ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表drivingtable)将被最先处理表TAB116,384条记录表TAB21条记录选择TAB2作为基础表(最好的方法)selectcount(*)fromtab1,tab2执行时间0.96秒选择TAB2作为基础表(不佳的方法)selectcount(*)fromtab2,tab1执行时间26.09秒,多表连接,交叉表为基础表,SELECT*FROMLOCATIONL,CATEGORYC,EMPEWHEREE.EMP_NOBETWEEN1000AND2000ANDE.CAT_NO=C.CAT_NOANDE.LOCN=L.LOCN将比下列SQL更有效率SELECT*FROMEMPE,LOCATIONL,CATEGORYCWHEREE.CAT_NO=C.CAT_NOANDE.LOCN=L.LOCNANDE.EMP_NOBETWEEN1000AND2000,WHERE子句中的连接顺序,原理:自下而上的顺序解析WHERE子句表之间的连接必须写在其他WHERE条件之前,可过滤掉最大数量记录的条件必须写在WHERE子句的末尾,WHERE子句中的连接顺序,例如:(低效,执行时间156.3秒)SELECTFROMEMPEWHERESAL50000ANDJOB=MANAGERAND2550000ANDJOB=MANAGER;,SELECT子句中避免使用*,ORACLE在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间子句中写出指定的列名,使用DECODE函数来减少处理时间,使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.例如:SELECTCOUNT(*),SUM(SAL)FROMEMPWHEREDEPT_NO=0020ANDENAMELIKESMITH%;SELECTCOUNT(*),SUM(SAL)FROMEMPWHEREDEPT_NO=0030ANDENAMELIKESMITH%;,使用DECODE函数来减少处理时间,使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.例如:你可以用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_SALFROMEMPWHEREENAMELIKESMITH%;类似的,DECODE函数也可以运用于GROUPBY和ORDERBY子句中.,尽量多使用COMMIT,只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:COMMIT所释放的资源:a.回滚段上用于恢复数据的信息.b.被程序语句获得的锁c.redologbuffer中的空间d.ORACLE为管理上述3种资源中的内部花费,用Where子句替换HAVING子句,避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤.这个处理需要排序,总计等操作.如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.,用Where子句替换HAVING子句,例如:低效:SELECTREGION,AVG(LOG_SIZE)FROMLOCATIONGROUPBYREGIONHAVINGREGIONREGION!=SYDNEYANDREGION!=PERTH高效SELECTREGION,AVG(LOG_SIZE)FROMLOCATIONWHEREREGIONREGION!=SYDNEYANDREGION!=PERTHGROUPBYREGION,用=替代,如果DEPTNO上有一个索引,高效:SELECT*FROMEMPWHEREDEPTNO=4低效:SELECT*FROMEMPWHEREDEPTNO3两者的区别在于,前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.,使用表的别名(Alias),当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.(译者注:Column歧义指的是由于SQL中不同的表具有相同的Column名,当SQL语句中出现这个Column时,SQL解析器无法判断这个Column的归属),减少访问数据库的次数,当执行每条SQL语句时,ORACLE在内部执行了许多工作:解析SQL语句,估算索引的利用率,绑定变量,读数据块等等.由此可见,减少访问数据库的次数,就能实际上减少ORACLE的工作量,减少访问数据库的次数,例如,以下有三种方法可以检索出雇员号等于0342或0291的职员.方法1(最低效)SELECTEMP_NAME,SALARY,GRADEFROMEMPWHEREEMP_NO=342;SELECTEMP_NAME,SALARY,GRADEFROMEMPWHEREEMP_NO=291;,减少访问数据库的次数,例如,以下有三种方法可以检索出雇员号等于0342或0291的职员.方法2(次低效)DECLARECURSORC1(E_NONUMBER)ISSELECTEMP_NAME,SALARY,GRADEFROMEMPWHEREEMP_NO=E_NO;BEGINOPENC1(342);FETCHC1INTO,.,.;.OPENC1(291);FETCHC1INTO,.,.;CLOSEC1;END;,减少访问数据库的次数,例如,以下有三种方法可以检索出雇员号等于0342或0291的职员.方法3(高效)SELECTA.EMP_NAME,A.SALARY,A.GRADE,B.EMP_NAME,B.SALARY,B.GRADEFROMEMPA,EMPBWHEREA.EMP_NO=342ANDB.EMP_NO=291;,减少对表的查询,在含有子查询的SQL语句中,要特别注意减少对表的查询,减少对表的查询,例如:低效SELECTTAB_NAMEFROMTABLESWHERETAB_NAME=(SELECTTAB_NAMEFROMTAB_COLUMNSWHEREVERSION=604)ANDDB_VER=(SELECTDB_VERFROMTAB_COLUMNSWHEREVERSION=604)高效SELECTTAB_NAMEFROMTABLESWHERE(TAB_NAME,DB_VER)=(SELECTTAB_NAME,DB_VERFROMTAB_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;,使用提示(Hints),对于表的访问,可以使用两种Hints.FULL和ROWID索引FULLhint告诉ORACLE使用全表扫描的方式访问指定表.索引hint告诉ORACLE使用基于索引的扫描方式.你不必说明具体的索引名称在不使用hint的情况下,以上的查询应该也会使用索引,然而,如果该索引的重复值过多而你的优化器是CBO,优化器就可能忽略索引.在这种情况下,你可以用INDEXhint强制ORACLE使用该索引.ORACLEhints还包括ALL_ROWS,FIRST_ROWS,RULE,USE_NL,USE_MERGE,USE_HASH等等参考文件sql语句优化.doc,识别低效执行的SQL语句,用下列SQL工具找出低效SQL:,用EXPLAINPLAN分析SQL语句,EXPLAINPLAN是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句.通过分析,我们就可以知道ORACLE是怎么样连接表,使用什么方式扫描表(索引扫描或全表扫描)以及使用到的索引名称.你需要按照从里到外,从上到下的次序解读分析的结果.EXPLAINPLAN分析的结果是用缩进的格式排列的,最内部的操作将被最先解读,如果两个操作处于同一层中,带有最小操作号的将被首先执行.NESTEDLOOP是少数不按照上述规则处理的操作,正确的执行路径是检查对NESTEDLOOP提供数据的操作,其中操作号最小的将被最先处理.,用EXPLAINPLAN分析SQL语句,通过实践,感到还是用SQLPLUS中的SETTRACE功能比较方便.举例:SQLl
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 银保部合规管理办法
- 电子发票如何管理办法
- 网络暴力规范管理办法
- 企业技术人员安全培训课件
- 社区三类人员管理办法
- 出血热疫苗接种方案课件
- 出租车安全生产培训课件
- 2025年浙江省烟草专卖局(公司)校园招聘考试试题(含答案)
- 超声心动图监测指标-洞察及研究
- 临床护理技术操作常见并发症的预防和处理考试试题(附答案)
- 贵州省榕江县2025年上半年事业单位公开遴选试题含答案分析
- 小学五年级数学学科培优辅差专项计划
- 浙江省宁波市五校2024-2025学年高一上学期期中考试生物试卷(含答案)
- 2025云南昆明巫家坝建设发展有限责任公司及下属公司第三季度招聘23人笔试模拟试题及答案解析
- 轮滑教学课件
- 2025年机动车检验检测机构授权签字人考核试题及答案
- 王志乐合规管理课件
- 新学期-启航出发-2025-2026学年初一上学期新生开学第一课主题班会
- 2025年秋数学(新)人教版三年级上课件:第1课时 观察物体
- GB/T 45701-2025校园配餐服务企业管理指南
- 第2课《中国人首次进入自己的空间站》课件
评论
0/150
提交评论