今年所做的优化,大的涉及到体系架构改造,涉及到利用cache,涉及到更改实现方式,小的如加hint,建索引更改sql语句等,一年下来,大大小小算下来也超过100个了。我稍微总结一下优化要具备什么,怎么来做?
为什么要优化?
举个简单的例子,某个sql每小时执行了300万次,逻辑读如果我们能从500下降到100,每小时就可以节省了上亿个逻辑读,优化可以让服务器更节约资源,优化可以让sql执行速度更快,提高用户体验。
1.理论一定要扎实。
数据库基础知识要扎实。比如索引为什么有些块delete后不能重用,而表delete后这些块很快会被重用掉的?想象索引B树 树状结果,想象关系型数据库heap表的最大特点是什么,就很容易理解上述问题了。
我一直认为会什么不重要,重要的是有扎实的基本功,勤奋,态度。态度能决定一切,很多东西要通过时间来沉淀的。叶开以前跟我说过,statspack中每个sql该排在报表中的哪个位置,我们是要清清楚楚的,这样出现问题时很容易快速定位出来。
2.怎么去判定sql的好坏?
通过逻辑读大小是很难断定sql是否优化,看是很难看出来的,要结合业务,返回的数据量来判断。
举个例子,web分页语句每页显示20行,单次逻辑读消耗在60左右,每小时执行次数在300万左右,这种sql的性能要学会评估,假设20行各分散在不同的块上,取20行的数据最多需要20个块+索引扫描取rowid 差不多在3-10个块左右,这个sql消耗的逻辑读差不多也就在30个块左右,逻辑读在60左右肯定是高了,如果我们能优化到30左右,每小时节省的逻辑读在300万执行次数*30,差不多节省了1个亿的逻辑读。我们这种系统中,有些sql每小时执行次数在百万级别之上,甚至在达到千万级别,sql优化要特别重视,也很有效。
3.理解分页list的两种写法
基本上是必修课了,有不用这个功能的应用吗?分页对于oracle来说有两种写法:普通写法和rowid写法,要深刻理解这两个写法,特别是rowid写法,优势是什么,用在哪个地方,具体的可以参考http://www.taobaodba.com,里面有多篇文章。
4.更改sql的实现方式
基本上我是禁止大表之间的关联查询的,如果核心表出现这种问题,我是坚决要求改掉,很多时候我宁愿开发拆成两个sql,分两次来执行。举个例子,比如汇总表(sborder_biz)和明细表(sborder_detail)是一对多的关系,一个汇总存在多个明细,我一般都是建议在明细表做的足够详细,做到不需要关联汇总表来实现。大家可以想象一下,关联两个大表,一个表走索引(t2.it_id索引)另一个表只能走关联的键值(t1.orderid)了,进而回表,对于oltp型的数据库来说,记录是非常分散的,回表的代价很大,t2返回多少条记录,就需要去回表t1的多少记录。
select t1.order_id,t2.createdate,t2.deleted from sborder_biz t1, sborder_detail t2
where t1.order_id = t2.order_id and t1.deleted = 0 and t2.it_id = :1 and t2.code = :2
5.建合适的索引
建合适的索引,特别是联合索引,需要很多技巧的,要根据查询条件,根据索引列的数据分布来建立,联合索引的好坏对sql性能影响非常大。
6.不用is null条件。
建表时,列要尽量设置成not null,尽量设置成不为空。
7.关注细节,关注应用实现方式
是的,一定要多关注细节,从小事做起,我认为这是最重要的。
小时候去河里拣田螺,一次一小颗,什么时候才能拣到一篮呢,优化也是,我们这么大的系统,刚开始优化很难出效果的,做好每一个sql,关注每一个sql的实现方式,积少成多,当你埋头在拣田螺时,篮子也渐渐满了。
稍微总结了这么几条,其他的会慢慢补充,比如如何使用cache,核心表如何设计等等,实际上面我所提到的几条,任何一条是否能做好,对数据库的性能影响都是极大的。
老大说我很多思想过于理想化,是的,架构,设计都不是我的专长,如果我都能看出问题来,那说明这不是小问题。通常我所负责的应用,我一般会去评估未来3-6个月的表现,进而加以改进,要多多未雨绸缪。
原文转自:http://blogread.cn/it/article/66