前言
- 大部分人通常认为一个数据库应用系统的性能瓶颈,最容易出现在数据的操作方面,而数据库应用系统的大部分数据操作都是通过数据库管理软件所提供的相关的接口完成。所以,数据库管理软件也就很自然的成为了数据库应用系统的性能瓶颈所在。
- 但是我们的应用系统的性能瓶颈真的完全是因为数据库管理软件和数据库主机自身造成的吗?
- 我们将通过本章的内容来进行一个深入的分析,以mysql为例。
一、商业需求对性能的影响
(一)背景
- 应用系统中的每个功能在设计初衷肯定是出于为用户提供某种服务,或者满足用户的某种需求,但是并不是每一个功能在最后都很成功,甚至有些功能的推出可能在整个系统中都是画蛇添足的。
- 不仅没有为用户提高任何体验度,也没有为用户改进多少功能易用性,反而在整个系统中成为一个累赘,带来资源的浪费。
- 不合理的需求造成资源投入产出比过低。
- 但是需求的合理很多时候并不是很容易界定,那么到底如何证明一个需求的是否合理呢?
- 一个不合理的需求对性能的影响也是很大的,因此,合理的需求界定,一定程度上就是制定出投入产出比的计算规则,这个规则的制定,是需要一定的项目经验以及项目需求的各种分析(如前期投入分析以及功能成品后期的效果统计分析)。
- 所以,作为技术员,在开发过程中要善于思考,站在一个产品经理的角度来换位思考并能给产品经理在项目需求对系统整体性能方面提出一定的建议。
(二)举例说明
- 需求:一个论坛帖子总量的统计,要求实时更新。
-
实现方案一:
(1)直接执行select count(*)。 (2)但是此sql语句在数据量越来越大的时候,不同的存储引擎会带来不同的性能问题。 (3)myisam存储引擎是非事务性存储引擎,并且其内部存在内置的计数器,直接保存着表明细的总数目,如果执行select count(*)那么将很容易就取出,即使在数据量很大的情况下也不会出现太大的问题。 (4)但是如果是InnoDB存储引擎,其内部并没有内置的计数器保存表明细总数量,每次执行select count(*)都会全表扫描 (5)由此可见,当数据量在很大的一个量级的时候,加上并发很大的情况下,很容易出现性能瓶颈。
-
实现方案二:
(1)方案一可以适用于myisam存储引擎,但是对于innodb存储引擎就不行了。 (2)那我们是否可以考虑为这个功能单独建立一个表,就只有一个字段一条记录,就存放这个统计量,每次有新的帖子的时候就更新一次这个统计量,到时候直接查询这个字段即可实现。 (3)这种方案也可能很好的提升查询效率,但是在我们的系统帖子产生很快的时候,在高峰时期可能每秒就有几十个甚至上百个帖子新增操作的时候,这个统计表可能又回出现问题。 (4)要么因为并发的问题造成统计结果不准确,要么因为锁资源争用严重造成整体性能的下降。
-
实现方案三:
(1)方案一和方案二都有一定的优缺点,但是如果我们想要在它们的缺陷处尽可能的完美避开性能瓶颈呢? (2)这时候我们重新考虑实时更新的需求,用户对于这个实时更新是很容易感知的吗? (3)当一个论坛的帖子数量很大了之后,到底有多少人会关注这个数量的实时变化?我想应该不会,因此,我们对此需求是不是可以不那么严格,是不是可以允许一定的偏差,达到准实时的标准? (4)基于此考虑,那么我们的方案三就可以创建一个统计表,然后通过定时任务隔一段时间更新一次统计表数据,这样既可以解决统计表查询的效率问题,又可以保证不影响发帖的效率,一举两得。
(三)总结
- 实际上,在我们应用的系统中还有很多类似的功能可以优化。
- 比如某些场合的列表页面参与列表的数据量达到一定的数据量级之后,完全可以不用准确的现实这个列表总共有多少条信息,总共分了多少页,只需要一个估计值或者一个时间段之前的统计值。
- 在很多应用系统中,实时和准实时,精确与基本准确,在很多地方所带来的性能性能消耗可能是几个性能的差别。
- 在系统性能优化中,应该尽量分析出那些不实时和不完全精确的地方,作出一些相应的调整,可能会给大家带来意想不到的巨大性能提升。
- 总结可见,商业需求对性能的影响有时候也是巨大的,这时候就需要制定出合理的投入产出比计算规则从而得到合理的需求,提升性能。
二、系统架构及实现对性能的影响
(一)背景
- 一个WEB应用系统,自然离不开Web应用程序(Web App)和应用程序服务器(App Server)。
- App Server我们能控制的内容不多,大多都是使用已经久经考验的成熟产品,大家能做的就只是通过一些简单的参数调整来进行调优,不做细究。
- 而Web App大部分都是各自公司根据业务需求自行开发,可控性要好很多。
- 所以我们应该从Web应用程序着手分析一个应用程序架构的不同设计对整个系统性能的影响更合适。
- 上一节商业需求告诉了我们一个系统应该有什么不应该有什么,系统架构则决定了我们系统的构建环境。
- 就像修建一栋房子一样,在清楚了这个房子的用途之后,会先有建筑设计师来画出一张基本的构造图,然后还需要结构设计师为我们设计出结构图。
- 系统架构设计的过程就和结构设计师设计结构图一样,需要为整个系统搭建出一个尽可能最优的框架,让整个系统能够有一个稳定高效的结构体系让我们实现各种商业需求。
(二)数据架构层面分析
- 数据层面上,我们数据库中存放的数据都适合在数据库中存放吗?
- 对于有些开发人员来说,数据库是一个操作最方便的万能存储中心,希望什么数据都存放在数据库中,不论是需要持久化的数据,还是临时存放的过程数据,不论是纯文本数据还是多媒体的二进制数据,都喜欢全部存放到数据库中。
- 其实,现在的很多数据库为我们提供了太多的功能,反而让很多并不是太了解数据库的人错误的使用了数据库的很多并不是很擅长或者对性能影响很大的功能,最后却全部怪罪在数据库上。
-
实际上,以下几类数据都是不适合在数据库中存放的:
(1)二进制多媒体数据: 【1】将二进制多媒体数据存放在数据库中,一个问题是数据库空间资源耗用非常严重,另一个问题是这些数据的存储很消耗数据库主机的cpu资源。 【2】这种数据主要包括图片、音频、视频和其他一些相关的二进制文件。 【3】这些数据的处理本不是数据库的优势,如果我们硬要将它们塞入数据库,肯定会造成数据库的处理资源消耗严重。 (2)流水队列数据: 【1】我们都知道,数据库为了保证事务的安全性以及可恢复性,都是需要记录所有变更的日志信息的。 【2】而流水队列数据的用途就决定了存放这种数据的表中的数据会不断的被INSERT、UPDATE、DELETE,而每一个操作都会生成与之对应的日志信息。 【3】在mysql中,如果是支持事务的存储引擎(InnoDB),这个日志的产生量将更是翻倍。 【4】而如果我们通过一些成熟的第三方队列软件来实现这个Queue数据的处理功能,性能将会成倍的提升。 (3)超大文本数据: 【1】对于5.0.3之前的mysql版本,varchar类型的数据最长只能存放255个字节,如果需要存储更长的文本数据到一个字段,我们就必须使用text类型(最大可存放64KB),甚至是更大的longtext类型(最大4G)。 【2】而text类型数据的处理性能要远比varchar类型数据的处理性能低下很多。 【3】从5.0.3版本开始,varchar类型的最大长度被调整为64KB,但是当实际数据小于255Bytes时,实际存储空间和数据的实际长度一样,可一旦数据长度超过了255Bytes之后,所占用的存储空间就是实际数据长度的两倍。 【4】所以,超大文本数据存放在数据库中不仅会带来性能低下的问题,还会带来空间占用的浪费问题。
-
是否合理的利用了应用层cache机制?
(1)对于web应用,活跃数据的数据量总是不会特别大,有些活跃数据更是很少变化。 (2)对于这中类型的数据,我们是否有必要每次需要的适合都去数据库中查询呢? (3)如果我们能够将变化相对较少的部分活跃数据通过应用层的cache机制cache到内存中,对性能的提升肯定是成数量级的,而且由于是活跃数据,对系统整体性能的影响也会很大。 (4)当然,通过cache机制成功的案例数不胜数,如何合理的通过cache技术让系统性能得到较大的提升也并不是通过寥寥几笔就能说明清楚的,这里根据以往经验列举一下什么样的数据适合通过cache技术来提升系统性能: 【1】系统各种配置及规则数据:由于这些配置信息变动的频率非常低,访问概率又很高,所以非常适合使用cache。 【2】活跃用户的基本信息数据: 「1」虽然我们经常会听到某某网站的用户量达到成百上千万,但是很少有系统的活跃用户量都能达到这个量级。 「2」也很少有用户没事干去将自己的基本信息改来改去。 「3」更为重要的一点是用户的基本信息在应用系统中的访问频率及其频繁。 「4」所以,用户基本信息的cache,很容易让整个系统的性能出现一个质的提升。 【3】活跃用户的个性化定制信息数据: 「1」虽然用户个性化定制的数据从访问频率来看,可能并没有用户的基本信息那么频繁,但相对于系统整体来说,也占了很大的比例,而且变更规律一样不会太多。 「2」从Ebay的PayPal通过mysql的memory存储引擎实现用户个性化定制数据的成功案例我们就能看出对这部分信息进行cache的价值。 「3」虽然通过mysql的memory存储引擎并不像我们传统意义上的cache机制,但正是对cache技术的合理利用和扩充造就了项目整体的成功。 【4】准实时的统计信息数据: 「1」所谓准实时的统计信息数据,实际上就是基于时间段的统计数据。 「2」这种数据不会实时更新,也很少需要增量更新,只有当达到重新build该统计数据的时候需要做一次全量更新操作。 「3」虽然这种数据即使通过数据库来读取效率可能也会很高,但是执行效率很高之后,同样会消耗不少资源。既然数据库资源非常珍贵,我们为什么不放在应用相关的cache中呢? 【5】其他一些访问频繁但是变更较少的数据: 「1」除了上述四种数据之外,在我们面对的各种系统环境中肯定还会有各种各样的变更较少但是访问很频繁的数据。 「2」只要合适,我们都可以对他们的访问从数据库移到cache中。
-
我们的数据层的实现都是最精简的吗?
(1)从以往的经验来看,一个合理的数据存取实现和一个拙劣的实现相比,在性能方面的差异经常会超出一个甚至几个数量级。 (2)我们先来分析一个实例: 【1】在我们的网站中,现在要实现每个用户查看各自相册列表,假设每个列表10张图片,能够在相片名称后边显示该相片的留言数量。 【2】实现方案一: 「1」通过“SELECT id,subject,url FROM photo WHERE user_id = ? limit 10”得到第一页的相片相关信息; 「2」通过第一步结果集中的10个相片的id循环运行十次"SELECT COUNT(*) FROM photo_comment WHERE photh_id = ?"来得到每张相片的回复数量然后再拼装展现对象。 【1】实现方案二: 「1」和方案一中的第一步一样的操作步骤; 「2」通过程序拼装上面得到的10个photo的id,再通过in查询“SELECT photo_id,count(*) FROM photo_comment WHERE photo_id in (?) GROUP BY photo_id”一次得到10个photo的所有回复数量,再组装两个结果集得到展现对象 (3)下面对两种方案做一下简单的比较: 【1】从mysql的sql执行数量来看,方案一为11条sql语句,方案二为2条sql语句; 【2】从应用程序于数据库交互来看,方案一是11次,方案二是2次; 【3】从数据库IO操作来看,简单假设每次sql为1个IO,方案一最少11次IO,方案二小于等于11次IO,而且只有当数据非常之离散的时候才会需要11次; 【4】从数据库处理的查询复杂度来看,方案一是两类很简单的查询,方案二有一条sql有group by操作,比第一种解决方案增加了排序分组操作; 【5】从应用程序结果集处理来看,方案一11次结果集的处理,方案二2次结果集的处理,但是方案二中第二次结果集数量是第一次的10倍; 【6】从应用程序数据处理来看,方案二比方案一多了一个拼装photo_id的过程。 (4)我们从以上6点做一个性能消耗的分析: 【1】由于mysql对客户端每次提交的sql不管是相同还是不同,都需要进行完全解析,这个动作主要消耗的资源是数据库主机的CPU,那么这里第一种方案和第二种方案消耗的CPU的比例是11:2。sql语句的解析动作在整个sql语句执行过程中的整体消耗的CPU比例是比较多的; 【2】应用程序与数据库交互消耗的资源基本上都在网络方面,同样是11:2; 【3】数据库IO操作资源消耗小于或者等于1:1; 【4】方案二需要比方案一多消耗内存资源进行排序分组操作,由于数据量不大,多出的消耗在语句整体消耗中占用比例会比较小,大概不会超过20%,大家可以针对性测试; 【5】结果集处理次数为11:2,但是方案二比方案一处理数量大,整体来说两次的性能消耗区别不大; 【6】应用程序数据处理方面所多出的这个photo_id的拼装所消耗的资源是非常小的,甚至比应用程序与mysql做一次简单的交互所消耗的资源还要少。 (5)整体分析后,得出结论,从整体消耗资源来看,方案二远远优于方案一。
-
过渡依赖数据库sql语句的功能造成数据库操作效率低下
(1)前面的案例是开发工程师过渡弱化SQL语句的功能造成的资源浪费案例,而这里我们再来分析一个完全相反的案例:在群组简介页面需要显示群名称和简介,每个群成员的nick_name,以及群主的个人签名信息。 (2)需求中所需信息存放在以下四个表中:user,user_profile,groups,user_group (3)方案一: 【1】SELECT name,description,user_type,nick_name,sign FROM groups,user_group,user ,user_profile WHERE groups.id = ? AND groups.id = user_group.group_id AND user_group.user_id = user.id AND user_profile.user_id = user.id (4)方案二: 【1】首先取得所有需要展示的group的相关信息和所有群组员的nick_name信息和组员类别: SELECT name,description,user_type,nick_name FROM groups,user_group,user WHERE groups.id = ? AND groups.id = user_group.group_id AND user_group.user_id = user.id 【2】然后在程序中通过上面结果集中的user_type找到群主的user_id再到user_profile表中取得群主的签名信息: SELECT sign FROM user_profile WHERE user_id = ? (5)大家应该能够看出两者的区别吧,两种解决方案最大的区别在于交互次数和 SQL复杂度。 (6)而带来的实际影响是第一种解决方案对user_profile表有不必要的访问(非群主的profile信息),造成IO访问的直接增加在20%左右。 (7)而大家都知道,IO操作在数据库应用系统中是非常昂贵的资源。尤其是当这个功能的PV较大的时候,第一种方案造成的IO损失是相当大的。
(三)其他架构影响
-
其他比较常见的架构设计实现不当带来的性能问题和资源浪费情况:
(1)重复执行相同的SQL造成资源浪费 (2)Cache系统的不合理利用导致Cache命中率低下造成数据库访问量的增加,同时也浪费了Cache系统的硬件资源投入; (3)对可扩展性的过度追求,促使系统设计的时候将对象拆得过于离散,造成系统中大量的复杂Join语句,而MySQL Server在各数据库系统中的主要优势在于处理简单逻辑的查询,这与其锁定的机制也有较大关系; (4)对数据库的过度依赖,将大量更适合存放于文件系统中的数据存入了数据库中,造成数据库资源的浪费,影响到系统的整体性能,如各种日志信息; (5)过度理想化系统的用户体验,使大量非核心业务消耗过多的资源,如大量不需要实时更新的数据做了实时统计计算。
三、Query 语句对系统性能的影响
- 前面一节我们了解了系统架构的实现方式对系统性能的影响,这一节我们将分析sql语句的差异对系统性能的影响。
- sql语句的优劣对性能是有影响的,但是到底有多大影响可能我们每个人都会有不同的体会,每个sql语句在优化之前和之后的性能差异也是各不相同的,所以对性能差异到底有多大我们这里就不做详细分析了。
- 我们重点分析实现同样功能的不同sql语句在性能方面会产生较大差异的根本原因。
-
为什么得到相同结果集的不同SQL语句,在执行性能上存在差异呢?这里我们先从sql语句在数据库中执行并获取所需数据的过程来进行分析。
(1)当mysql server的连接线程接收到Client端发送过来的sql请求之后,会经过一系列的分解Parse,进行相应的分析。 (2)然后mysql会通过查询优化器模块根据该sql所涉及到的数据表的相关统计信息进行计算分析,然后再得出一个mysql认为最合理最优化的数据访问方式,就是我们平时说得“执行计划”。 (3)再根据得到的执行计划通过存储引擎接口来获取相应数据。 (4)最后再将存储引擎返回的数据进行相关处理,并以Client端要求的格式作为结果集返回给Client端的应用程序。 (5)注意:这里所说的统计数据,是mysql通过ANALYZE TABLE命令同志mysql对表的相关数据做分析之后所获得的一些数据统计量。这些统计数据对mysql优化器来说非常重要,优化器所生成的执行计划的好坏,主要就是由这些统计数据所决定的。 (6)我们都知道,在数据库管理软件中,最大的性能瓶颈就是在于磁盘IO,也就是数据存取操作上面。 (7)而对于同一份数据,当我们以不同方式去寻找某一点的数据时,所需要读取的数据量可能会有天壤之别,所消耗的资源也自然是区别深大。 (8)所以,当我们需要从数据库中查询某个数据的时候,所消耗资源的多少主要取决于数据库以一个什么样的数据读取方式来完成我们的查询请求,也就是取决于sql语句的执行计划。 (9)而对于唯一sql语句来说,经过mysql Parse之后分解后的结构都是固定的,只要统计信息稳定,其执行计划基本上都是比较固定的。 (10)而不同写法的sql语句,经过Mysql Parse之后分解的结构就可能会不同,即使优化器使用完全一样的统计信息来进行优化,最后所得到的执行计划也可能完全不一样。 (11)而执行计划是决定一个sql语句最终的资源消耗量的主要因素。 (12)所以,实现功能完全一样的SQL语句,在性能上面可能会有差别巨大的性能消耗。 (13)当然,如果功能一样,而且经过 MySQL的优化器优化之后的执行计划也完全一致的不同SQL语句在资源消耗方面可能就相差很小了。当然这里所指的消耗主要是IO资源的消耗,并不包括 CPU的消耗。
- 分析具体的sql语句对性能对影响,有两种方式,一种就是explain执行计划,一种就是通过实际执行后的profile数据的验证。具体的详细分析这里不做探究,以后具体举例探究。
四、Schema设计对系统性能的影响
(一)背景
- 前面,我们已经分析了数据库应用系统的软环境中应用系统的架构设计和系统中与数据库交互的sql语句对系统性能的影响。接下来,我们再分析下系统的数据模型设计实现对系统的性能影响。更通俗的讲就是数据库的Schema设计对系统性能的影响。
- 在很多人看来,数据库Schema设计是一件非常简单的事情,就大体按照系统设计时候的相关实体对象对应成一个一个的表格基本上就可以了。
- 然后为了功能上尽可能的容易扩展,再根据数据库范式规则进行调整,做到第三范式或者第四范式,基本就算完事了。但是数据库的Schema设计真的这么容易吗?
- 这里,我们暂时不讨论什么样的Schema设计是最优的设计,而是先通过一个实际的实例来展示Schema结构的不一样在性能方面所带来的差异。
(二)示例
- 需求概述:一个简单的讨论区系统,需要有用户,用户组,组讨论区这三部分基本功能
-
简要分析:
(1)需要存放用户数据的表; (2)需要存放分组信息和存放用户与组关系的表 (3)需要存放讨论信息的表;
-
方案一:分别用用四个表来存放用户,分组,用户与组关系以及各组的讨论帖子的信息。
-
方案二:用户与用户属性表分开
-
两方案比较:
(1)我们先来比较下两个解决方案所设计的Schema的区别。 (2)区别主要体现在两点。一个区别就是group_message表中添加了author字段来存放发帖作者的昵称,与user表的nick_name相对应,另外一个就是方案二将user表和group_message表都拆分成了两个表,关系分别一一对应。 (3)方案二看起来复杂一些,首先是表的数量多2个,然后是group_message中冗余了作者的昵称。 (4)我们试想一下,一个讨论区系统,访问最多的页面会是什么? (5)我想大家都会很清楚是帖子标题列表页面。而帖子标题列表页面最主要的信息就是都是来自 group_message表中,同时帖子标题后面的作者一般都是通过用户名(昵称)来展示。按照第一种解决方案来设计的 Schema,我们就需要执行类似如下这样的SQL语句来得到数据: 【1】SELECT t.id, t.subject,user.id, u.nick_name FROM ( SELECT id, user_id, subject FROM group_message WHERE group_id = ? ORDER BY gmt_modified DESC LIMIT 20 ) t, user u WHERE t.user_id = u.id (6)但是方案二所需执行的sql就会简单很多: SELECT t.id, t.subject, t.user_id, t.author FROM group_message WHERE group_id = ? ORDER BY gmt_modified DESC LIMIT 20 (7)两个sql相比较,很明显可以看出方案一需要join两个表的数据,与方案二的sql相比性能相差很大,尤其是如果第一个再写的差一点,性能更是非常糟糕,两者所带来的资源消耗就更相差玄虚了。 (8)不仅仅如此,由于第一个方案中的group_message表中还包含一个大字段“content”,该字段所存放的信息要占整个表的绝大部分存储空间,但在这条系统中执行最频繁的 SQL之一中是完全不需要该字段所存放信息的,但是由于这个SQL又没办法做到不访问group_message表的数据,所以第一条SQL在数据读取过程中会需要读取大量没有任何意义的数据。 (9)在系统中用户数据的读取也是比较频繁的,但是大多数地方所需要的用户数据都只是用户的几个基本属性,如用户的id,昵称,密码,状态,邮箱等,所以将用户表的这几个属性单独分离出来后,也会让大量的SQL语句在运行的时候减少数据的检索量,从而提高性能。 (10)可能有人会觉得,在我们将一个表分成两个表的时候,我们如果要访问被分拆出去的信息的时候,性能不是就会变差了吗?是的,对于那些需要访问如user的sign,msn等原来只需要一个表就可以完成的SQL来说,现在都需要两条SQL来完成,性能确实会 有所降低,但是由于两个表都是一对一的关联关系,关联字段的过滤性也非常高,而且这样的查询需求在整个系统中所占有的比例也并不高,所以这里所带来的性能损失实际上要远远小于在其他SQL上所节省出来的资源,所以完全不必为此担心
五、硬件环境对系统性能的影响
- 在本章之前的所有部分都是介绍的整个系统中的软件环境对系统性能的影响,这一节我们将从系统硬件环境来分析对数据库系统的影响,并从数据库服务器主机的角度来做一些针对性的优化建议。
- 任何一个系统的硬件环境都会对起性能起到非常关键的作用
- 而数据库应用系统环境中,由于数据库自身的特点和在系统中的角色决定了他在整个系统中是最难以扩展的部分。所以在大多数环境下,数据库服务器主机(或者主机集群)的性能在很大程度上决定了整个应用系统的性能。
- 既然我们的数据库主机资源如此重要,肯定很多读者朋友会希望知道,数据库服务器主机的各部分硬件到底谁最重要,各部分对整体性能的影响各自所占的比例是多少,以便能够根据这些比例选取合适的主机机型作为数据库主机。但是我只能很遗憾的告诉大家,没有任何一个定律或者法则可以很准确的给出这个答案。
- 当然,大家也不必太沮丧。虽然没有哪个法则可以准确的知道我们到底该如何选配一个主机的各部分硬件,但是根据应用类型的不同,总体上还是有一个可以大致遵循的原则可以参考的。
-
三类影响数据库主机性能的最主要因素部件
(1)与IO相关的磁盘和内存: 【1】首先,数据库主机是存取数据的地方,那么其IO操作自然不会少,所以数据库主机的IO性能肯定是需要最优先考虑的一个因素,这一点不管是什么类型的数据库应用都是适用的。 【2】不过,这里的IO性能并不仅仅只是指物理的磁盘IO,而是主机的整体IO性能,是主机整个IO系统的总体IO性能。 【3】而IO性能本身又可以分为两类,一类是每秒可提供的IO访问次数,也就是我们常说的IOPS数量,还有一种就是每秒的IO总流量,也就是我们常说的IO吞吐量。 【4】在主机中决定 IO性能部件主要由磁盘和内存所决定,当然也包括各种与IO相关的板卡。 (2)CPU: 【1】其次,由于数据库主机和普通的应用程序服务器相比,资源要相对集中很多,单台主机上所需要进行的计算量自然也就比较多,所以数据库主机的CPU处理能力也不能忽视。 (3)网络设备: 【1】最后,由于数据库负责数据的存储,与各应用程序的交互中传递的数据量比其他各类服务器都要多,所以数据库主机的网络设备的性能也可能会成为系统的瓶颈。
- 由于上面这三类部件是影响数据库主机性能的最主要因素,其他部件成为性能瓶颈的几率要小很多
-
所以后面我们通过对各种类型的应用做一个简单的分析,再针对性的给出这三类部件的基本选型建议。
(1)典型OLTP应用系统 【1】对于各种数据库系统环境中大家最常见的OLTP系统 【2】其特点是并发量大,整体数据量比较多,但每次访问的数据比较少,且访问的数据比较离散,活跃数据占总体数据的比例不是太大。 【3】对于这类系统的数据库实际上是最难维护,最难以优化的,对主机整体性能要求也是最高的。因为他不仅访问量很高,数据量也不小。 【4】针对上面的这些特点和分析,我们可以对OLTP的得出一个大致的方向: 「1」虽然系统总体数据量较大,但是系统活跃数据在数据总量中所占的比例不大,那么我们可以通过扩大内存容量来尽可能多的将活跃数据cache到内存中; 「2」 虽然IO访问非常频繁,但是每次访问的数据量较少且很离散,那么我们对磁盘存储的要求是IOPS表现要很好,吞吐量是次要因素; 「3」 并发量很高,CPU每秒所要处理的请求自然也就很多,所以CPU处理能力需要比较强劲; 「4」 虽然与客户端的每次交互的数据量并不是特别大,但是网络交互非常频繁,所以主机与客户端交互的网络设备对流量能力也要求不能太弱。 (2)典型OLAP应用系统 【1】用于数据分析的OLAP系统的主要特点就是数据量非常大,并发访问不多,但每次访问所需要检索的数据量都比较多,而且数据访问相对较为集中,没有太明显的活跃数据概念。 【2】基于OLAP系统的各种特点和相应的分析,针对OLAP系统硬件优化的大致策略如下: 「1」数据量非常大,所以磁盘存储系统的单位容量需要尽量大一些; 「2」单次访问数据量较大,而且访问数据比较集中,那么对IO系统的性能要求是需要有尽可能大的每秒IO吞吐量,所以应该选用每秒吞吐量尽可能大的磁盘; 「3」虽然IO性能要求也比较高,但是并发请求较少,所以CPU处理能力较难成为性能瓶颈,所以CPU处理能力没有太苛刻的要求; 「4」虽然每次请求的访问量很大,但是执行过程中的数据大都不会返回给客户端,最终返回给客户端的数据量都较小,所以和客户端交互的网络设备要求并不是太高; 「5」此外,由于OLAP系统由于其每次运算过程较长,可以很好的并行化,所以一般的OLAP系统都是由多台主机构成的一个集群,而集群中主机与主机之间的数据交互量一般来说都是非常大的,所以在集群中主机之间的网络设备要求很高。 (3)除了以上两个典型应用之外,还有一类比较特殊的应用系统,他们的数据量不是特别大,但是访问请求及其频繁,而且大部分是读请求。可能每秒需要提供上万甚至几万次请求,每次请求都非常简单,可能大部分都只有一条或者几条比较小的记录返回,就比如基于数据库的 DNS服务就是这样类型的服务。 「1」虽然数据量小,但是访问极其频繁,所以可以通过较大的内存来 cache住大部分的数据,这能够保证非常高的命中率,磁盘IO量比较小,所以磁盘也不需要特别高性能的; 「2」并发请求非常频繁,需要较强的CPU处理能力才能处理; 「3」虽然应用与数据库交互量非常大,但是每次交互数据较少,总体流量虽然也会较大,但是一般来说普通的千兆网卡已经足够了。
- 在很多人看来,性能的根本决定因素是硬件性能的好坏。
- 但实际上,硬件性能只能在某些阶段对系统性能产生根本性影响。
- 当我们的CPU处理能力足够的多,IO系统的处理能力足够强的时候,如果我们的应用架构和业务实现不够优化,一个本来很简单的实现非得绕很多个弯子来回交互多次,那再强的硬件也没有用,因为来回的交互总是需要消耗时间。
- 所以,在应用系统的硬件配置方面,我们应该要以一个理性的眼光来看待,只有合适的才是最好的。并不是说硬件资源越好,系统性能就一定会越好。
- 而且,硬件系统本身总是有一个扩展极限的,如果我们一味的希望通过升级硬件性能来解决系统的性能问题,那么总有一天将会遇到无法逾越的瓶颈。
总结
- 简单来说,可以通过下面三句话来简单的概括数据库应用系统的性能优化:商业需求合理化,系统架构最优化,逻辑实现精简化,硬件设施理性化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。