【IT168 专稿】本文根据【2016 第七届中国数据库技术大会】(微信搜索DTCC2014,关注关注中国数据库技术大会公众号)现场演讲嘉宾鲍倚天老师分享内容整理而成。录音整理及文字编辑IT168@ZYY@老鱼
讲师简介
Maxgauge产品咨询顾问,高级优化工程师,Oracle OCM,长期致力于Maxgauge产品咨询和实施,系统性能优化方法论的研究和实践工作,拥有在 电信,金融,物流,制造,政府等多个行业的系统性能优化项目经验。
正文:
大家下午好,我是来自Maxgauge的鲍倚天,我目前主要负责整个系统优化项目的咨询和实施工作,我今天演讲的主题是:基于云的系统性能诊断与优化。和大家交流一下我关于数据库性能管理的技术跟经验。我的分享主要分为以下四个部分:
虽然现在整个是基于云的一种方式,但实际上我们所采用的服务方式还是线上和线下都有的方式。那么,为什么要基于云呢?根据我的项目实施经验来看,由于市场在不断变化,如果仍然按照传统的项目实施模式,整个的成本包括人力将会占项目很大的比重。这几年也是由于市场变化导致成本不断增加。我们就考虑采用一种基于云的方式,通过远程服务剖析目前服务方式的弊端。也就是说实际上是采用一种成本很高的方式去降低项目的实施成本。
性能管理及优化服务现存问题
接下来我们来看一下性能管理及优化服务现存问题,实际上我针对所有可能存在的问题做了一个梳理,最终就表现为以下4个方面:
1、 人力成本与日俱增。近几年由于人力成本的增加导致项目成本增加。根据以往的经验来看,一个项目里的人力成本或者说直接成本大概占比50%左右,如果加上项目产生的其他费用和销售费用,整个项目的毛利率大概只有20%—30%,这还算控制的比较好的。由于整个成本在增加,如果我们派人员去现场服务的话,利润会非常少,这就会导致人力成本的增加。
2、 IT传统环境的变化。由于互联网对传统行业的冲击导致在传统行业做项目非常费劲,这种服务方式的持续化非常差。
3、 性能管理和优化工作通常需要通过出差的形式完成。由于很多优化项目不在本地,需要安排相应人员出差,项目周期越长,成本就越高。从长远来看,这样的项目在项目控制上有很大的风险。
4、 工程师培养周期长。在做项目的过程中,我们要把一个有一定基础的工程师培养成可以独立做项目的中高级工程师,大概需要花两年的时间,甚至更久。
所以我们一定要改变现状。我们要做到通过服务的云化、工具化和流程化提高人员复用率。通过这些改变,在整个程度上提升技术的标准化、产品的成熟度和服务的流程化。
要达到这三个目的,我觉得要通过以下三个方面来解决,第一是云技术,第二是产品和工具的标准化、流程化,第三是采用基于中心化的服务。对于云技术来说,现在云服务技术已经非常成熟了,我们应该思考怎样通过云服务技术来改变这种方式。在公司内部除了需要采用云技术方式外,也要加大整个公司的产品研发力度,把一些原来需要人工解决的问题或工作变成工具化、自动化的方式。尽量尝试让一个人同时做多个项目,变相提高人员复用率,通过这种方式把整个项目的实施变成一种持续化的方式。
基于云的系统性能管理和优化服务技术架构
我们所服务、监控的对象是基于企业的所有数据库和应用平台,我们为了监控这样一个平台,首先会在整个内网放一个云服务网关,通过这个网关可以与外面的云服务对接,我们在应用和数据库所搜集到的性能数据都会通过云网关传输到云服务平台进行长期存储。我们也会在云服务平台部署一些监控和优化工具,让优化人员或DBA可以通过云服务平台来进行各种服务。
接下来我们看一下详细的部署架构:我们的监控方式是在数据库服务器和移动服务器上部署Agent,Agent会对数据库和应用数据进行实时搜集。我们将所有数据库和应用搜集到的数据放到统一的监控器中进行存储,然后由监控器实时反馈到云服务平台。实际上监控方式一共有2种,一种是实时监控数据,一种是历史监控数据。实时监控数据我们可以通过监控器将监控数据反馈到云服务平台上,优化人员能够实时看到这些监控数据,对于历史数据我们就需要在监控服务器上进行保存,我们也可以在内网部署多台监控服务器,一旦监控平台出现问题,我们可以用其他备用的监控服务器接管,将出现的问题及时传送给备用平台进而保证整个数据中间不会产生断点。
接下来看一下我们搜集方式的具体架构:实际上我们适用于多种数据库,我们在数据库上部署监控实际是使用一个进程进行搜集,当开始搜集时,我们的进程会对整个数据库进行实时搜集,搜集完之后整个进程会将所有的性能数据实时发送给监控平台,在监控平台里会有一组数据搜集进程,当数据发送给数据搜集进程之后会对这些数据进行解析,解析完之后把这些性能数据存到监控平台上的知识库里面,用户实际上就可以通过管理界面对整个知识库进行管理操作。
我们目前所采用的搜集方式和传统的搜集方式有什么区别呢?传统的搜集方式在数据库负载很高的时候,通过工具去关联数据、查询性能数据,本身会对数据库性能产生一些影响。当数据库发生挂起时,无法通过这样的方式查询性能数据。
我们目前通过Agent进行搜集,我们通过进程直接访问SGA采集数据,不通过任何数据库接口访问,从实时性、稳定性、时效性的角度来说这种方式远高于传统方式。
这个是我们的一个针对搜集数据的一个展示,搜集频度是以1秒为单位进行搜集的,那么以一秒为单位进行搜集,就是为了保证性能数据的精确以及全面,高度精细的性能数据为各种无法预知的故障和性能问题提供了一个可靠的分析依据。
前面说到的很多架构实践方法是比较通用的,而且云服务技术本身也比较成熟,但这样的方式还是会有一定的局限性。问题并不在技术本身而是在于客户环境的问题,比如说给客户实施这样的服务和架构,除了会降低我们自身企业项目的投入成本之外,还会降低客户的付出成本,提升整个服务的持续性,因为数据是从企业内部发送到云服务平台进行存储的。但对于安全性要求比较高的客户来说,这种方式不太适用,对这样的客户,我们会在企业内部提供服务,这就是我们所说的局限性。我们搜集的数据是整个数据库和应用性能数据,对性能数据来说,我们并不会关联到客户的生产数据,在设计架构之前和客户确认好数据,把这种搜集方式对整个系统的影响都确定好之后,这样的方式一般不会出现问题。
基于云的系统性能管理和服务技术架构能做什么样的事情呢?主要是两个方面:一是优化,二是监控诊断。先说一下性能优化,对于数据库来说最重要的性能优化就是索引,系统里的大部分问题都来源于数据库,对于数据库来说它的主要性能就是IO。IO产生的问题主要有两方面,一是sql语句,二是索引设计。针对sql语句,很多情况下优化的都是线上系统,如果修改一个sql语句,对一般客户来说代价比较大,所以我们就选择一种成本比较低的方式进行性能优化--索引优化。
基于云的性能优化和诊断方法
基于云的索引优化设计及应用步骤:
1、 全面搜集表的读取类型。
2、 选定索引列对象和统计分析其数据分布。
3、 统计列使用频次和运算符。
4、 组合索引列及顺序选择。
5、 模拟和测试
6、 调整部分sql语句。当前面所有步骤都无法通过索引设计方式解决性能问题的时候,才考虑通过修改sql语句达到性能优化。
7、 索引部署及监控。
最重要的就是搜集,我们搜集的所有数据均来源于存储的性能数据。因为它以秒为单位进行搜集,所以这样的数据比较全面。搜集完之后,通过工具对搜集的数据按照一定规则进行解析,解析时需要将这些读取类型的数据以表为单位进行归类,因为一个表上的读取类型是有限的,一种sql语句就能代表一种业务处理场景,所以我们要对数据以表为单位进行归类。归类完成后需要对结果进行判定,判断哪些表最终需要做优化,确定优化对象的维度。读取类型较多的表属于业务上比较核心的表,这样的表判定为优先需要优化的对象。
以下实际上就是做完索引设计之后的产出物,对于这样的sales表来说,我们通过解析所有的sql语句,最终得到了如下的11种读取类型,最终对应11种业务处理场景。每一种读取类型都对应若干条sql语句,从以往的案例来看,这样的读取类型对应的语句有几十、几百条都是正常的,要根据表的使用核心程度来进行判定,以下是整个的产出物案例:
接下来看一下我们怎样进行解析:以一条sql语句为例,假定一条sql语句上有3个表。我们先看下Where条件都有哪些,我们仅仅保留字段名称以及运算符。我们先以X表来看,在X表上,就有这样的一个条件INOUT_NO等于一个常量,还有一个跟它相关的条件是X.INOUT_NO=Y. INOUT_NO,我们把这种关联条件进行标识,这种标识在读取类型里就是一个关联条件,以上是X表。我们再看Y表,与Y表相关的条件有2个,一个是INOUT_NO,一个是ITEM_ID,也是关联条件,这些属于Y表。所以说我们通过解析sql语句,取出读取类型,以表的类型进行组合,最终这样的sql语句我们一共得到3种读取类型。因为最终我们设计索引的时候是以表为单位进行设计的,所以我们最终解析的时候也是以这种格式进行解析,他的输出方式就是按照表为单位进行输出。这是我们整合的通过解析sql语句进行分类的过程。
接下来看一下索引设计的时候如何覆盖:我们可以看到一个有40条sql语句的表,通过刚才的方式来解析最终得到11个读取类型。接下来需要对这些读取类型进行分类,由于第一个点最重要,所以先对第一个点进行设计,首先要考虑第一列里哪些条件的使用频度最多,经过筛选最终得到4种标红的读取条件是使用频度最高的。
接下来就基于这样的结果进行第一列设计,第一列以CUST_NO为设计索引,我在设计的时候除了看使用频度,也考虑这个列的离散度和列运算符。比如,通过查看这个列的离散度读取类型,我发现这个条件适合作为第一列设计索引,所以我就把它设为第一列,我在设计中可以看到它到底覆盖多少种读取类型。通过判定发现以此为开头设计第一个索引,会比单独使用其他索引作为第一列要好,那么这个就是以CUST_NO为第一列索引设计的过程。
接下来我们再看一个CRD_NO,也是通过查看该列的离散度和运算符,以CRD_NO为第一列索引的时候可以覆盖3个。实际上我们设计索引就是以这样的方式一个一个去查看,当然这样的方式肯定不会依靠人工去做。因为一张表的读取类型可能有成百上千,人工查看肯定实现不了,所以我们要通过工具辅助我们做这些事情。这个案例最终设计出来的4个索引,最终满足了11种读取类型和40多条sql语句的读取要求,这就是覆盖的过程。
覆盖完之后就需要考虑一个问题:需要查看现有索引跟已有读取类型的契合度。契合度比较高的索引可以进行复用,复用完之后剩下的读取类型契合度比较低的,我们就再次进行分类。对分类完的索引列进行使用频次、运算符以及离散度的排序。通过工具排序后,人工查看排序的结果能不能满足整个索引的要求。因为工具无法探知最终的结果是否满足我们的要求,所以这个过程是需要人工判定的。通过这些过程,我们的一个索引就设计完成了。然后再对整个索引进行模拟。
做完上述工作后,最重要的就是测试了。需要强调的是最终的成果不能直接部署到市场活动中,所以要进行测试。测试环境要求数据分布度与生产环境具有高度的相似性。因为最终被选取与否与整个的数据分布度是有关系的。比如说这样一个字段如果在数据分布度完全一样的环境里面,这个列无论是有10万还是100万条数据,最终的选择性一定是一样的。所以我们就需要进行测试,在测试环节部署完之后,就需要一条一条去看,将当前表上的所有索引都跑一遍,查看是否满足我的每条语句的执行计划,是否能够用到这个索引,这个过程也是工具帮我们做的事情。根据计划无法使用到的索引,再通过局部调整将这些索引进行语句单独优化,这就是测试的过程。
这个是基于我刚所说的整个架构的流程,首要的就是搜集,所有的数据在知识库里都是保存好的;搜集完之后就要以表为单位进行解析;解析完之后就是通过访问路径以表为单位进行输出;然后通过工具对所有访问路径进行分组、排序,实际上就是根据离散度、使用次数进行排序。这就是通过工具实现索引的设计方法。
除了索引设计外,另外一个方法是性能监控诊断。性能监控诊断体系主要分为3层:
1、Source Layer。最底层从SGA、数据库和OS中搜集性能信息放到收集层。
2、Gathering Layer。收集层把这些数据分类解析存到云平台知识库,然后再通过平台、界面管理整个性能数据。
3、Display Layer。针对性能监控主要分两方面:第一个非常重要的方面是当前数据库发生告急或出现错误性信息时,我们可以通过Email或短信的方式发给相关责任人,以便他们快速发现问题及时响应;另外一个就是专线指标,保存专线数据库性能指标的历史趋势数据,这些数据实际上帮助DBA更快的发现数据库的性能波动,对这些波动及时采取措施优化或针对可能出现的问题及时预防。
基于云的性能监控和诊断方式如下:
当发现系统的一个点或一段时间出现问题时,我可以在系统性能趋势曲线上选择出问题的点或时间段,该曲线会直接关联到当前有问题的规划,最终关联到与其相关的sql语句。优化人员最终可以通过这种方式掌握sql级别的信息,从而可以及时掌握可能发生的问题。
接下来看一下具体如何实现?比如说有这样一个时间段,我会发现在这个时间段里会出现一个反复的性能波动,通过系统平台统计就会发现,在这样的性能波动里它的逻辑读、一天最高的峰值最多达到200GB左右,然后选择一天之中趋势最高的峰值去分析它的性能。
如下,这个图在24小时内的性能波动是存在的。针对这样的性能波动,我们还要进行进一步的细化,选择1个小时的数据进行分析。通过分析1个小时的性能数据,发现整个的IO一直是保持在比较高的状态。
通过分析发现,只有这个时间段会话一直保持在活动的状态,首先就分析出它的IO主要是由于这样的会话所导致的。接下来,我要关联会话。
实际上就是通过点击会话详情查看会话是怎样操作的,在这样的时间段和会话里,他们都在执行同样的语句,我们需要查看语句的状态,再通过会话的详情关联到sql语句,这就是刚才会话在这1小时的时间段内一直在执行的sql语句。
上面可以看到这个SQL的详细信息,那么其实主要耗时全部是在CPU时间上面,那么我就要通过查看SQL和执行计划来分析SQL的问题。
那么我们详细看一下这个语句问题,实际上这个就是两个表之间的一个子查询,那么通过分析我们发现,条件yurref的离散度非常的好,有27万种值,也就是说实际上子查询内部的查询结果只有几条数据,那么为执行计划没有选择从内侧开始执行呢,通过分析执行计划就可以发现,serial=0这个条件在执行计划表并不是在子查询的表一级过滤的,于是通过去查看表结构上面的列就发现,实际上这个条件是在子查询外侧的表上的一个列,但是由于却被放到了子查询内部,由于子查询中,主查询和子查询属于主从关系。所以导致外侧的表为了去获得这个条件的去反复扫描内侧的表几十万次,从而也导致了产生大量的IO。
通过诊断我们发现了问题,实际上就是通过反复扫描内侧表导致整个时间非常长,也导致大量的逻辑IO,这就是一条逻辑语句的分析。接下来的优化措施就很明显了,就需要把这个条件拿到外侧表就可以了。
所以通过简单的sql修改,最终的优化结果就是将6000多秒的一个语句在2秒内完成。这就是我们整个的系统流程方式。
前面说了很多关于架构和方法到底能给我们带来什么样的价值。我觉得最终可分为三个方面:
1、监控自动化。监控自动化正是通过程序的方式帮助我们主动搜集性能信息以及存储性能信息,它代替了原来需要人工去干预的方式存储信息,提升效率。通过这种方式使得原来花很长时间去定位、模拟、分析性能的问题大幅度地减少诊断和分析的时间。
2、优化半自动化。优化半自动化通过解析分类和工具的方式半自动化的帮我们做优化,在整个优化过程中帮我们做优化工作,达到事半功倍的效果。
3、中心化服务。降低成本,提升人员复用率。
实施案例
接下来说我们做过的一个案例:实际上以前我们实施项目的时候都是去现场部署各种各样的工具,通过工具去搜集客户的数据,对于这样的方式来说搜集是很重要的,那么怎样保证搜集的数据是最全面的呢?根据以往的经验来看,我们最终所确定的搜集时间窗口在一个业务周期里面,但一个业务周期的时间很难判定。
现在所采用的方式,通过把员工调动起来,我们从平台数据库直接搜集系统性能数据,对这些数据我们采用一个周期的窗口搜集、解析,这样的数据对我们来说就已经足够全面了。针对这样的结果做索引工作,最终得到的结果也是比较准确的。一旦某些sql语句没有覆盖到,而把索引修改删除之后,这样的一种方式会产生新的系统性能问题,这个也是需要避免的。
对于什么时候结束搜集数据,它的时间判定点是:我们会统计整个读取类型的种类和sql语句的增量情况,我们在搜集很长一段时间之后,增量变得非常不明显或者在一段时间内没有增加,我们就认为搜集已经完成了。基于这样的搜集结果做测试分析也是比较好的。
这就是我们做设计的一个结果,我们实际上仅通过表格设计优化的方式,就使得整个核心系统对IO消耗有几十、几百倍的下降,同样这种下降也导致系统资源消耗的下降。
这是我们客户最终优化整个后台IO的一个曲线图,逐步升级优化之后,之前与之后的对比是很明显的。这是我们的一个优化案例。
最后跟大家总结一下,其实这样的方式也是比较好的,通过这种方式提高人员复用率,降低成本。该方法的局限性在于对中小型客户或者是一些对安全性要求不是特别高的客户,我们会提供这样的服务。我们的服务方式也在不断改进,力争在项目的实施过程中能够实现这样一种项目方式。最终为自身将低成本,为客户减少付出。我们也在做这样的尝试。谢谢大家!