大家在开发后端应用的时候,相信多数情况下都遇到过数据库性能瓶颈的问题,在解决数据库瓶颈时,通常的做法是先有数据库管理员检查有没有慢查询,然后在看慢查询相关的字段,是不是没有创建索引,然后在排查数据库配置是否合理,最后分析下是否需要扩充硬件。虽然经过了前面数据库端的仔细优化,但是很多情况下数据库性能依然很低。尤其是在并发的情况下,其实这是有业务逻辑代码和 SQL 语句没有被优化,因此影响了数据库的性能。

先来看看究竟是什么对数据库的性能造成了影响,对数据库性能有影响的因素,可以分为几个方面,我们先来从大体上看一下。

服务器硬件

第一个对数据库性能有影响的,显而易见的因素来源于数据库服务器的硬件。每当我们的个人计算机响应不够快时,我们总会说是因为我 们的 CPU 不够快,内存不够多,或者磁盘 I/O太慢这样的因素引起的。同样这些问题的服务器上也会存在,所以这是人们最容易找到的对性能有影响的因素之一。

服务器系统

第二个对性能有影响的因素是服务器所使用的操作系统。同样我们常用的个人电脑来举例,可能我们会发现我们的电脑在有的操作系统上运行比在其他操作系统上更加的顺畅。而对于同样的操作系统,有时我们的配置参数不同,运行的流畅程度也会有不同。所以拿我们比较熟悉的 Windows XP 系统来说,默认的 TCP 方数只有十个。而当我们把这个限制调大之后,我们就会发现,可以大大的加快我们下载的速度。同样服务器系统也是有区别的,而对于服务器系统的优化参数,也要比我们的个人桌面操作系统要多得多。对这些参数的调整也会影响到我们的服务器的整体性能。

数据库存储引擎的选择

而第三个影响性能的因素是我们所选择的 MySQL 服务器的存储引擎。众所周知啊 MySQL 的最大特点就是它的插件式的存储引擎的设计。我们可以根据我们的业务的不同需求,自由的选择,我们所需要的使用的任何一种生素引擎。而不同存储引擎呢也有不同的特点,比如说 MyISAM 这种存储引擎,它是不支持事务的,同时它使用的是一种表级锁。而 InnoDB 则是一种事物级的存储引擎,同时可以完美的支持行级锁,以及事物的 ACID 特性。但是我们并不能就因此说 InnoDB 一定要比 MyISAM 要好。在有些场景下我们会发现,使用麦项目可能会更加的合适。关于存储引擎的选择呢,我们下面还会有详细的介绍。

数据库参数配置

而影响数据库性能的第四个因素,就是我们的这个数据库服务器的配置参数。MySQL 有上百项的这种配置参数,不同的存储引擎也有相应的配置参数。这其中有的参数对性能的影响几乎是微乎其微的。但是有了参数却对性能有着决定性的影响,所以呢根据我们所选择的这个存储引擎和业务模式的不同,对不同的参数进行优化。也是我们作为数据库开发的一个关键技能。

数据库结构设计和 SQL 语句

前面所有的因素加起来的一对性能的影响呢,可能也没有这最后一个对数据库性能的影响巨大。在最后一个就是数据库表结构的设计和 SQL 语句的执行效率对数据库的性能的影响。我们在进行数据库结构设计的时候,一定要考虑到今后我们要在这个数据库中执行什么样的 SQL 语句,来对我们所设计的这个表结构进行查询和更新。只有这样,才能设计出符合我们对 SQL 查询优化逻辑的表结构。

慢查询可以说是大多数数据库问题的最优过手,而很多的这种有效率问题的 SQL 就是由于我们的数据库的库表结构设计不合理而产生的。而对于这类思想来说,也是最难优化的,因为我们的业务一旦上线,就很难再对相应的库表结构进行更改了。所以我们数据库的性能优化的重点,在于数据库的库表结构的设计和 SQL 语句的编写和优化上。

以上就是所有会对我们的数据库造成影响的一些因素。下面我们来详细看一下以上所提到的这些对性能有影响的因素呢,我们应该如何进行优化。

CUP 资源和可用内存大小

大家都知道,在双十一促销中,大家可以看到,每当大促系统繁忙的时候,我们可以监控到的 CPU 资源和可能内存资源都是十分紧张的。特别是对一些计算密集型的应用,CPU 资源就越可能的去影响整个系统的性能,成为系统的瓶颈。

所以首先,对 MySQL 性能有影响的,就是这两种硬件资源,也就是 CPU 资源和可用的内存大小。

另一方面,当我们工作所需要的热数据的大小远远超过可用内存大小时,I/O 系统就会成为我们的瓶颈。网络我们也可以看作是另外一种 I/O 资源。网络对性能的影响往往发生在大量的数据被查询时,特别是当我们使用 MeMcache 这样的存储引擎。当缓存大量失效时,就会产生大量的网络传输,所以影响服务器的性能。

所以当出现 I/O 系统瓶颈时,我们最有效的方法就升级 I/O 子系统来增加更多的内存。网络 及 I/O 资源就是对我们这个数据库性能有影响的第二个硬件因素。

那么下面呢我们会分别为大家介绍一下服务器硬件对 MySQL 性能会产生什么样的影响和如何对他们进行优化。

首先来看我们如何选择 CPU,经常有人会问我这样的问题。我们是需要更多的 CPU 还是需要更快的 CPU。这个问题在我们升级服务器或者是在购买新的服务器硬件的时候,经常会被负责采购硬件的这种同事的问道。

他们经常的会要求我们选择我们所需要的 CPU 的频率和 CPU 的数量,当然在完美的情况下,对于这两个选项,我们都想要做的最好。我们想要最高频率 CPU,同时也想要更多的 CPU 的核心数。

但是现实往往是很残酷的,总是由于某些原因迫使我们只能选择这两种中的一种,当然了这些在某些原因呢,最主要的还是成本的因素。那么这个时候,我们就先要对下面的事情,有了一些了解之后,才能做出正确的选择。首先我们要看我们的应用是否是 CPU 密集型的。
而对于 CPU 密集型的应用,要加快 SQL 语句的处理速度。显然我们需要的是更好的 CPU 而不是更多的 CPU。

这里还有一点要注意,对于目前版本的 MySQL 而言,还不支持多 CPU 对同一 SQL 的并发处理。也就是说,不管 SQL 多复杂或者多简单,我们都只能用到一个 CPU 的核心进行处理。这时多个 CPU 对提高 SQL 的处理效率,显然是没有帮助的。接下来呢我们还要了解一下我们的系统的并发量是如何的。

并发量如何

虽然单个 CPU 无法利用到多个 CPU 资源,而如果我们要提高系统的吞吐量,或者说是并发处理量呢,那么这时我们就需要 CPU 越多越好了。

我们来想象一下,如果说一个 CPU 可以处理一个 SQL,那么是不是可以说如果我们有四十个 SQL 就可以同时处理四十个 SQL 呢?细心的朋友呢可能已经注意到了,我们定义过一个衡量数据库处理能力的指标,也就是 QPS 。QPS 指同时处理的 SQL 的数量。

这里要强调一下是 QPS 指的是每秒钟处理 SQL 的数量。而这里所说的并发处理四十个 SQL,可能是在纳秒级的,这完全取决于我们所要处理的 SQL 的执行情况,MySQL 目前被大量应用在外部类的应用中,这类应用的并发量通常是非常大的。所以在这种情况下,CPU 的数量就显得比频率可能更加重要一些了。

如何考虑 MYSQL 版本

同时我们还要考虑所使用的 MySQL 的版本,是的,你没有看错,我们所使用的 MySQL 的版本也会决定我们如何选择 CPU, 老版本的 MySQL 对于多核的 CPU 的支持并不好。

对于 MySQL 5.0 之前的版本,这个限制是非常严重的。而对于现在的 MySQL 5.6 和 MySQL 5.7 版本来说呢,对多核 MySQL 的支持也有了很大的改善。我们可以放心的使用十六核或者三十二核这样的 CPU。所以要使用多个 CPU 的话,还要要建议大家的使用最新版的板 MySQL,这样才能达到最好的性能。

如何选择 CPU

关于如何选择 CPU 呢?还有最后一个问题呢,也需要我们来注意的。这个问题,现在来说,应该已经不是问题了。就是我们是选择 32 位的 CPU,还是选择 64 位的 CPU。这个选项现在看来完全是多余的。因为 64 位架构的 CPU,现在已经成为默认的一种配置了。我们现在就是想买 32 位的服务器,可能也买不到了。同时 MySQL 对 64 位架构的 CPU 已经做到完美的支持。所以下面的注意事项才是我们关于这个选项的重点。

大家要小心的是,在 64 位架构 CPU上运行 32 位的操作系统。大家不要以为这种情况是很难发生的,其实这种情况是经常发生的,特别是在一些云服务器或虚拟主机上。

当然有了一些公司自己的服务器上,也可能会出现这种情况。这一般是由于运维人员在安装操作系统的时候使用了错误的版本的操作系统而造成的。不要小看忽略这个问题,对于一些大公司,也有可能会出现这样的错误。特别是对于一些非生产环境,比如说开发和测试环境。更容易出现这种情况了。32 位的操作系统,意味着我们不能使用大量的内存,并且在 32 位系统上,任何一个单独的进程都不能寻址到 4G 以上的内存。

所以大家又知道 MySQL 表现的是一个单线程的一种服务。所以如果我们使用 32 位的操作系统,实际上是对 MySQL 性能有一个极大的限制,所以大家一定要注意这一点。

如何选择内存

说完了 CPU,我们再来说说内存,内存的大小直接影响了数据库性能。目前内存的 I/O 效应要远远高于磁盘。就是和 SSD 或者 Fusion - IO 这样的高速四核相比,内存在 I/O 速率也要高得多。所以把数据缓存到内存中进行读取,可以大大提高数据库的性能。

在常用的 MySQL 存储引擎中,MyISAM 会把索引缓存到内存中,而数据通过操作系统来进行缓存。而以 InnoDB 存储引擎会同时在内存中缓存数据和索引,从而提高数据库的运行效率。

关于内存的配置,还有几个提示需要大家注意。内存虽然是越多越好,但是对性能的影响也是有个限度的,我们不能指望通过增加内存而无限的增加系统的性能。

数据库可以利用的内存是有限的。一般当缓存的数据和磁盘存储的数据,也就是说当所有的数据都已经被缓存到内存后。在增加缓存内存的大小就是没有意义了。

举个例子来说,如果我们的数据文件的大小是 100G ,这时候我们的内存只有 64G 的情况下,我们可以通过增加服务器内存,扩大数据库的缓冲区和大小来获取性能的提升。不过我们的数据文件是 100G 而我们的内存已经是 256G,并且数据库的缓存池的大小也达到了 196G 的情况下。就不能指望通过增加服务器内存的方式来获得性能提升了。当然这也不是绝对的,虽然数据库不能利用多出来的内存,但是对于的内存呢,有增加操作系统等其他服务的性能。

第二点要注意的是,缓存不但会对读有益处,同时对写也是有益处的。关于缓存的一个常见的误区是只有毒会在缓存中受益。如果有足够的内存,就完全可以避免磁盘读取的请求。如果所有的数据文件都可以放在内存中。一旦服务器缓存热起来,也就是说所有数据都被缓存起来之后,所有的读操作都会在缓存中命中。但是写入是不同的问题,写入可以像读一样在内存中完成。但迟早我们要把它写入到内存中的数据把它提入到磁盘上。

但是虽然是这样的,缓存还是对写入有好的影响。它虽然不能避免磁盘的写入操作,但是可以对写操作进行延缓,把多次写入变成一次写入。比如我们许多电商网站中,对每个商品会提供一个浏览量的这种计数器。这时如果我们每次又有用户查看这个商品的时候,都不信这个周期的话,显然会造成大量的这种 I/O 操作。但如果我们只通过更新内存中的计数器,当计数器级增到一定数量,比如 100 以后再统一写入到磁盘,这样就把 100 次写入做变成了一次操作,从而增加得到了服务器的性能。数据库就提供了类似的一些功能,可以在缓存池中把对同一数据的多次写操作合并成一次。然后在最终写入到磁盘设备上。

那么我们如何配置内存呢?这个涉及到内存的选择问题,这里还有一个建议,就是说内存的主频和 CPU 的主频的是类似的。所以建议大家选择服务器所支持的主频最高的内存,频率越高表示内存的读取速度也会越快。因此我们在选择内存时,应该选择我们服务器主板所能支持的频率最高的内存。还应该注意的是服务器内存通常来说是组成购买升级的,每个通道内存尽量要使用相同的一种品牌,相同颗粒,相同频率,相同电压、相同校验技术和相同型号的内存条。

另外就是我们选择的内存单条容量要尽可能的大,当然这就意味着我们所花费的成本也会增加,当然也可以根据我们目前的数据库的大小来选择合适的内存。比如我们目前的数据库热数据大小可能有100G,那么我们可能选择 128G 内存就已经足够了。但是还是要考虑到数据的增长速度,以及增长幅度等因素。所以选择更大一些内存,比如 256G 可能会更好,这样避免短时间内就要升级内存的问题。