罗海雄
云和恩墨优化专家
ITPUB论坛数据库管理版版主,ITPUB全国SQL大赛冠军得主,他还是资深的架构师和性能优化专家,对SQL优化和理解尤其深入;作为业内知名的技术传播者之一,经常出席各类技术分享活动。从开发到性能管理,他有着超过10年的企业级系统设计和优化经验。曾经服务于甲骨文公司,组织和主讲过多次《甲骨文技术开发人员日》和《Oracl圆桌会议》,在任职甲骨文公司之前,他还曾经服务于大型制造企业中芯国际,具备丰富的制造行业系统架构经验。
主题简介在数据库运维中我们会遇到各种各样的问题,这些问题的根源可能很明显,也可能被某种表象掩盖而使我们认不清。所以运维面临的两大问题就是,第一我们没有看清本质,第二应用不允许修改。那么我们如何解决这两个问题,是每一个运维者都应该思考的。今晚的分享将会从三个方面来进行。如何准确定位问题,如何不修改应用进行优化,以及如何通过SQL审核防患未然。
大家好。我是云和恩墨公司的专家罗海雄,主要专长于性能优化这个领域,包括数据库的优化,SQL优化等。今天给大家分享的主题是“如何在无法修改应用时进行数据库优化”。
我先从一个真实的案例说起。我们的一个客户,是一个汽车经销商,他们的财务系统出现了严重的性能问题。
这是他们的CPU压力的示意图。
红色的是CPU使用量,绿色的是CPU空闲,黑色的是IO等待。我们可以看到,在图的中间部分,也就是月底的时候,CPU使用量已经达到80-90%,而CPUIdl已经接近0了。
中间似乎还有一段CPU空闲%,其实是由于数据库压力太大,主机自动重启了。这种情况已经严重影响他们公司财务系统的月结工作。他们赶紧找到我们公司,我一看AWR,发现大量SQL执行时间很长。
从表里可以看到,第一个SQL平均一次执行需要秒,后面还有几个SQL单次执行在秒以上,显然有很大问题。
发现明显有部分SQL写法上存在问题,正是这些SQL,导致数据库压力过大。
其中一条SQL是这个样子的:
几个表都是几千万条记录的大表,r.FSrcEntryId是个选择都很高的栏位,si.FID是个主键,si.FId也是主键。
T_IM_SalIssuEntry是外连接的驱动表,但是上面没有直接的条件。
T_IM_SalIssuBill和T_BOT_RELATIONENTRY都是被驱动表,上面有两个条件:
si.FTransactionTypIDIN(:3,:4)和r.FSrcEntryIdIN(:5,:6)
这种情况下,由于被驱动表已经有了确定值,逻辑上来说,外连接和内连接是等价的,但是Oracl10g的优化器没有为这种情况做优化,导致在优化前,走了大表的全表扫描。
这一类SQL不少。我们最早的建议就是修改部分写法存在问题的SQL,从源头入手,尝试解决。比如说,把LEFTOUTERJOIN改成普通JOIN,逻辑上是一样的,就能走刚才的好的执行计划。
但是,应用开发厂商表示,由于这个版本比较老,他们已经没有专门的人员对代码进行维护,无法修改SQL。
这就是作为一个系统维护DBA,经常会碰到的问题。
系统刚上线,一切很美好...
一两年后,由于数据量的积累,用户数增多,功能点使用增多等原因,会使负荷逐渐增加,从而出现性能问题。根据我们的经验,在这些性能问题里面,SQL的问题可能占了80%.但是,由于种种原因,可能就是没法修改SQL.
比如说:
--使用封装好的商业套件
--外包开发,开发商已经离场
--自行开发,但开放部门不愿意配合进行代码修改
这就到了今天的主题:“如何在无法修改应用时进行数据库优化”
总的来说,可以从硬件和软件两个方面去解决:硬件方面,可以通过增加或者CPU,增加内存,做一定的改善。也可以通过升级成增加RAC,也可以增加CPU的处理能力。存储方面,升级更好地存储,针对一些I/O要求比较高的系统,也一种优化的手段。
这是我们的一个客户,通过把存储介质升级到PCIEFlash卡,极大的改善了I/O性能问题,是整个系统的性能得到了极大的提升。
我们公司的zData产品,通过高速的PCIEFlash卡,结合超大带宽,超小延迟的高速IB网络,也可以非常有效地提高I/O的性能,总体性能是传统存储的10倍以上。这样,在不修改任何SQL的情况下,就轻松解决了I/O的瓶颈,提高的系统的性能。当然,对于不差钱的单位/企业,使用Oracl的Exadata也是一种方法;很简便的、不修改应用就能明显提高系统性能的方法。动硬件往往涉及到预算。不增加开销的情况下,也可以通过数据库的层面做一些优化。
回到我一开始介绍的那个案例。
经过研究,我们发现,LEFTOUTERJOIN不能等价转换成普通JOIN是Oracl10g的行为模式。在Oracl11g中,优化器做了升级,能够识别并内部进行这种转换。而恰巧,用户用的是Oracl11g的数据库,只是由于应用开发方的要求,把优化器模式设为了10.2.0.1.
最终,通过和应用开发方,使用方的多次沟通和测试,最终把优化器模式设为了11.2.0,从而解决了最大的问题。
当然,LEFTOUTERJOIN只是其中一个问题,后来,在这个客户的数据库上,我们还有针对性的建立了多个索引。最终,在没有修改任何SQL的情况下,彻底解决了用户的系统性能问题。
通常来说,数据库层面的优化包括
参数调整:内存参数,优化器参数等
表结构调整:索引,并行度,分区
SQL执行计划调整:SQLProfil,SPM,SQLPatch
其它:Cach表、统计信息、物化视图+查询重写、数据归档等等
合适的优化器参数,会使你系统索引的问题看起来很简单,但往往是最有效的方法之一。大家讨论的比较多,我就不深入了。分区以及数据归档也是一个常用的手段。实际上,数据都是有生命周期的。很多用户的数据库里面,存了很多已经不需要的数据,通过清理、归档这些数据,往往也能获得比较高的优化效果。
还有一些情况,SQL写的并没有问题,但由于种种原因,数据库经常走错执行计划;这时候,通过改写SQL,增加Hint是一种常见解决方式。在无法修改SQL的情况下,也可以通过一些手段对SQL执行计划进行固定。
这些手段主要包括有:
SQLProfil(Oracl10g以后)
SQLPlanBaslinManagmnt(Oracl11g以后)
SQLPatch
Outlin
SQLprofil在Oracl10g引入
通过为特定的SQL文本指定优化器的一些信息,从而引导优化器生成更为合理的SQL执行计划。达到不修改SQL文本就可以改变并指定执行计划的目的。
SQL-Profil主要通过dbms_sqltun包进行控制。时间关系,今天就不为大家演示了。
SQLPlanManagmnt在Oracl11g引入
通过为特定的SQL指定已知SQL执行计划,强制优化器选择已经指定的SQL执行计划,从而达到不修改SQL文本即可修改执行计划的目的。
可以指定多个可用执行计划供优化器选择。
可以和SQLTuningAdvisor一起用
可以自动收集运行库中SQL作为已知执行计划。
也可以手工设置。
SQLPlanManagmnt主要通过DBMS_SPM包进行控制,SQLPatch是一种强行给SQL加Hint的方法,主要通过sys.dbms_sqldiag_intrnal.i_crat_patch进行。
不同的数据库优化方式对整个数据库影响面各有不同,在使用的时候,需要谨慎的程度也不一样。
经典问题分享问题一
关于SQLProfil使用方法有什么好的推荐的书籍或者文档介绍之类的
关于SQLprofil,推荐老熊的两篇文章