oracle 10g 排序优化,Oracle 10g SQL 优化再学习

从8i到10g,Oracle不断进化自己的SQL Tuning智能,一些秘籍级的优化口诀已经失效。

但我喜欢失效,不用记口诀,操个Toad for Oracle Xpert ,按照大方向舒舒服服的调优才是爱做的事情。

1.Excution Plan     Excution Plan是最基本的调优概念,不管你的调优吹得如何天花乱堕,结果还是要由Excution plan来显示Oracle 最终用什么索引、按什么顺序连接各表,Full Table Scan还是Access by Rowid Index,瓶颈在什么地方。如果没有它的指导,一切调优都是蒙的。

2.Toad for Oracle Xpert

用它来调优在真的好舒服。Quest吞并了Lecco后,将它整合到了Toad 的SQL Tunning里面:最清晰的执行计划显示,自动生成N条等价SQL、给出优化建议,不同SQL执行计划的对比,还有实际执行的逻辑读、物理读数据等等一目了然。

3.索引   大部分的性能问题其实都是索引应用的问题,Where子句、Order By、Group By 都要用到索引。

一般开发人员认为将索引建全了就可以下班回家了,实则还有颇多的思量和陷阱。

3.1 索引列上不要进行计算

这是最最普遍的失效陷阱,比如where trunc(order_date)=trunc(sysdate), i+2>4。索引失效的原因也简单,索引是针对原值建的二叉树,你将列值*3/4+2折腾一番后,原来的二叉树当然就用不上了。解决的方法:

1. 换成等价语法,比如trunc(order_date) 换成

where order_date>trunc(sysdate)-1andorder_date

2.    特别为计算建立函数索引

createindexI_XXXXonshop_order(trunc(order_date))

3.    将计算从等号左边移到右边

这是针对某些无心之失的纠正,把a*2>4 改为a>4/2;把TO_CHAR(zip) = '94002' 改为zip = TO_NUMBER('94002');

3.2 CBO与索引选择性     建了索引也不一定会被Oracle用的,就像个挑食的孩子。基于成本的优化器(CBO, Cost-Based Optimizer),会先看看表的大小,还有索引的重复度,再决定用还是不用。表中有100 条记录而其中有80 个不重复的索引键值. 这个索引的选择性就是80/100 = 0.8,留意Toad里显示索引的Selective和Cardinailty。实在不听话时,就要用hints来调教。

另外,where语句存在多条索引可用时,只会选择其中一条。所以索引也不是越多越好:)

3.3 索引重建

传说中数据更新频繁导致有20%的碎片时,Oracle就会放弃这个索引。宁可信其有之下,应该时常alter index rebuild一下。

3.4 其他要注意的地方      不要使用Not,如goods_no != 2,要改为

wheregoods_no>2andgoods_no<2

不要使用is null , 如WHERE DEPT_CODE IS NOT NULL 要改为

WHEREDEPT_CODE>=0;

3.5 select 的列如果全是索引列时   又如果没有where 条件,或者where条件全部是索引列时,Oracle 将直接从索引里获取数据而不去读真实的数据表,这样子理论上会快很多,比如

selectorder_no,order_timefromshop_orderwhereshop_no=4

当order_no,order_time,shop_no 这三列全为索引列时,你将看到一个和平时完全不同的执行计划。

3.6 位图索引     传说中当数据值较少,比如某些表示分类、状态的列,应该建位图索引而不是普通的二叉树索引,否则效率低下。不过看执行计划,这些位图索引鲜有被Oracle临幸的。

4.减少查询往返和查询的表

这也是很简单的大道理,程序与Oracle交互的成本极高,所以一个查询能完成的不要分开两次查,如果一个循环执行1万条查询的,怎么都快不到哪里去了。

4.1 封装PL/SQL存储过程  最高级的做法是把循环的操作封装到PL/SQL写的存储过程里,因为存储过程都在服务端执行,所以没有数据往返的消耗。

4.2 封装PL/SQL内部函数  有机会,将一些查询封装到函数里,而在普通SQL里使用这些函数,同样是很有效的优化。

4.3 Decode/Case  但存储过程也麻烦,所以有case/decode把几条条件基本相同的重复查询合并为一条的用法:

SELECTCOUNT(CASEWHENprice<13THEN1ELSEnullEND) low,COUNT(CASEWHENpriceBETWEEN13AND15THEN1ELSEnullEND) med,COUNT(CASEWHENprice>15THEN1ELSEnullEND) highFROMproducts;

4.4 一种Where/Update语法

SELECTTAB_NAMEFROMTABLESWHERE(TAB_NAME,DB_VER)=((SELECTTAB_NAME,DB_VER)FROMTAB_COLUMNSWHEREVERSION=604)

UPDATEEMPSET(EMP_CAT, SAL_RANGE)=(SELECTMAX(CATEGORY)FROMEMP_CATEGORIES)

5.其他优化

5.1RowID和ROWNUM

连Hibernate 新版也支持ROWID了,证明它非常有用。比如号称删除重复数据的最快写法:

DELETEFROMEMP EWHEREE.ROWID>(SELECTMIN(X.ROWID)FROMEMP XWHEREX.EMP_NO=E.EMP_NO);

6.终极秘技 -Hints

这是Oracle DBA的玩具,也是终极武器,比如Oracle在CBO,RBO中所做的选择总不合自己心水时,可以用它来强力调教一下Oracle,结果经常让人喜出望外。

如果开发人员没那么多时间来专门学习它,可以依靠Toad SQL opmitzer 来自动生成这些提示,然后对比一下各种提示的实际效果。不过随着10g智能的进化,hints的惊喜少了。

7. 找出要优化的Top SQL    磨了这么久的枪,如果找不到敌人是件郁闷的事情。

幸亏10g这方面做得非常好。进入Web管理界面,就能看到当前或者任意一天的SQL列表,按性能排序。

有了它,SQL Trace和TKPROF都可以不用了。

Tracker: http://www.blogjava.net/calvin/archive/2005/11/11/19276.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值