7.1 瓶颈
许多不同的硬件都可以影响MySQL的性能,但我们认为最常见的两个瓶颈是CPU和I/O。当数据可以放在内存中或者可以从磁盘中以足够快的速度读取时,CPU可能出现瓶颈。把大量数据集放到大容量内存中,以现在的硬件条件完全是可行的。
I/O瓶颈,一般发生在工作所需的数据远远超过有效内存容量的时候。如果应用程序是分布在网络上的,或者如果有大量查询或低延迟要求,瓶颈可能转移到网络上,而不再是磁盘I/O。
7.2 选择CPU
7.2.1 更快还是更多
当遇到CPU密集型的工作时,MySQL通常可以从更快的CPU中获益。
7.2.2 CPU架构
可能大部分MySQL实例(不含嵌入式)都运行在Intel或AMD芯片的x86结构下。
7.2.3 多核
多CPU在联机事务处理系统的场景非常有用。这些系统通常执行许多小的操作,并且是从多个连接发起请求,因此可以在多个CPU上运行。在这样的环境中,并发可能成为瓶颈。大多数Web应用程序属于这一类。
7.3 平衡内存和磁盘资源
配置大量内存的原因不是因为可以在内存中可以保存大量数据:最终目的是避免磁盘I/O,因为磁盘I/O比在内存中访问数据要慢得多。关键是要平衡磁盘和内存的大小、速度、成本和其他因素,以便为工作负载提供高性能的表现。
7.3.1 随机I/O和顺序I/O
数据库服务器同时使用顺序和随机I/O,随机I/O从缓存中收益最多。典型的情况是“热点”数据随机分布。因此,缓存这些数据将有助于避免昂贵的磁盘寻道。相反,顺序读取一般只需要扫描一次数据,所以缓存对它是没用的,除非能完全放在内存中缓存起来。
7.3.2 缓存,读和写
如果有足够的内存,就完全可以避免磁盘读取请求。如果所有的数据文件都可以放在内存中,一旦服务器缓存“热”起来了,所有读操作都会在缓存命中。虽然还是会有逻辑读取,不过物理读取就没有了。但是写入是不同的问题。写入可以像读一样可以在内存中完成,但迟早要被写入到磁盘,所有它是需要持久化的。换句话说,缓存可延缓写入,但不能像消除读取一样消除写入,但不能像消除读取一样消除写入。
7.3.3 工作集
每个应用程序都有一个数据“工作集”,就是做这个工作确实需要用到的数据。很多数据库都有大量不在工作集内的数据。
7.3.4 寻找有效的内存/磁盘比例
最好的方式是通过实验和基准测试。大多数时候不可能这么做,所以需要用数据的一个子集来做基准测试,看看将会发生什么。测试的目标是一个可接受的缓存命中率。缓存未命中时当有查询请求数据时,数据不能再内存中命中,服务器需要从磁盘获取数据。
7.3.5 选择磁盘
存储容量、传输速度、访问时间、主轴转速、物理尺寸
7.4 固态存储
固态存储设备采用非易失性闪存芯片而不是磁性盘片组成。它们也被称为NVRAM,或非易失性随机存取存储器。固态存储设备没有移动部件,这使得它们表现得跟硬盘驱动器有很大不同。
7.4.1 闪存概述
闪存最重要的特征是可以迅速完成多次小单位读取,但是写入更有挑战性。闪存不能再没有做擦除操作前改写一个单元,并且一次必须擦除一个大块。擦除周期是缓慢的,并且最终会磨损整个块。一个块可容忍的擦除周期次数取决于所使用的底层技术。
7.4.2 闪存技术
有两种主要的闪存设备:分别是单层单元(SLC)和多层单元(MLC)。
SLC每个单元存储数据的一个比特:可以是0或1。SLC相对更昂贵,但非常快,并且擦写寿命高达100000个写周期,具体值取决于供应商和型号。这听起来好像不多,但在现实中一个好的SLC设备应该持续使用大约20年左右,甚至比卡上的控制器更加耐用和可靠。缺点是存储密度相对较低,所以不能再每个设备上得到那么多的空间。
MLC有更高的存储密度,成本更低,但是速度和耐擦写性也下降了。一个不错的MLC设备可获得10000写循环周期。
7.4.3 闪存的基准测试
闪存有一个三阶段模式,称为A-B-C性能特征。它们开始阶段运行非常快,然后垃圾回收器开始工作,这将导致在一段时间内,设备处于过渡到稳定状态的阶段,最后进入一个稳定状态。所有我们测试过的设备都有这个特点。
当然,我们在意的是阶段C的性能,所以基准测试只会测量这个部分的运行过程。这意味着基准测试要做的不仅仅是基准测试:还需要先进行一下预热,然后才能进行基准测试。但是,定义预热的终点和基准测试的起点会非常棘手。
7.4.4 固态硬盘驱动器(SSD)
SSD模拟SATA硬盘驱动器,这是一个兼容性功能:替换SATA硬盘不需要任何特殊的去掉程序或接口。
7.4.5 PCIe存储设备
相对于SATA SSD,它没有尝试模拟硬盘驱动器。这种设计是好事:服务器和硬盘驱动器直接的接口不能完全发挥散存的性能。SAS/SATA互联网带宽比PCIe低,所以PCIe对高性能需求更好。其设备延迟也低得多,因为它们在物理上也更靠近CPU。
7.5 为备库选择硬件
与主库相似,但是也有些不同。如果正计划建一个备库做容灾,通常需要跟主库差不多的配置。不管备库是不是作为一个主库的备用库,都应该强大到足以承担主库上发生的所有写入,额外的不利因素是备库 只能序列化串行执行。
7.6 RAID性能优化
存储引擎通常把数据和索引都保存在一个大文件中,这意味着RAID(磁盘冗余阵列)存储大量数据通常是最可行的方法。RAID可以帮助做冗余、扩展缓存容量、缓存以及加速。
7.6.1 故障转移、恢复和镜像
RAID配置都提供了冗余。这很重要,但很容易让人低估磁盘同时发生故障的可能性。千万不要认为RAID能够提供一个强有力的数据安全性保证。
RAID不能消除甚至减少备份d额需求。当出现问题的时候,恢复时间要看控制器、RAID等级、阵列大小、硬盘速度,以及重建阵列时是否需要保存服务器在线。
7.6.2 平衡硬件RAID和软件RAID
操作系统、文件系统和操作系统看到的驱动器数据之间的相互作用可以是复杂的。Bug,限制或至少错误配置,都可能把性能远远降低到理论值。
7.6.3 RAID配置和缓存
配置RAID控制器通常有几种方法,一是可以在启动时进入自带的设置工具,或从命令行中运行。虽然大多数控制器提供了很多选项,但其中有两个是我们特别关注的,一是条带化阵列的块大小,还有就是控制器板载缓存。
7.7 SAN和NAS
两个外部文件存储设备加载到服务器的方法。不同的是访问存储的方式。访问SAN设备时通过块接口,服务器直接看到一块硬盘并且可以像硬盘一样使用,但是NAS设备通过基于文件的协议来访问。SAN设备通常通过光纤通道协议或iSCSI连接到服务器,而NAS设备使用标准的网络连接。还有一些设备可以同时通过这两种方式访问。
7.8 选择操作系统
GNU/Linux如今是高性能MySQL最常用的操作系统, 但是MySQL本身可以运行在很多操作系统上。
7.9 选择文件系统
文件系统的选择非常依赖操作系统。在许多系统中,如Windows就只有1-2个选择,并且只有一个(NTFS)真的是能用的。比较而言,GNU/Linux则支持多种文件系统。
实际基准测试表明,大多数文件系统在很多方面都非常接近,但测试文件系统的性能则不容易。文件系统的性能是与工作负载相关的,没有哪个文件系统可以说最优越。大部分情况下,给定的文件系统不会明显地表现地与其他文件系统不一样,除非遇到文件系统的限制。
7.10 选择磁盘队列调度策略
在GNU/Linux上,队列调度决定了到块设备的请求实际上发送到底层设备的顺序。默认情况下使用cfq(完全攻破排队)策略。随意使用的笔记本和台式机使用这个调度策略没有问题,并且有助于防止I/O饥饿,但是用于服务器则有问题。在MySQL的工作负载类型下,cfq会导致性能很差的响应时间,因为会在队列中延迟一下不必要的请求。
7.11 线程
MySQL每个连接使用一个线程,另外还有内部处理线程、特殊用途的线程,以及所有存储引擎创建的线程。
无论哪种方式,MySQL都需要大量的线程才能有效地工作。MySQL确实需要内核级线程的支持,而不只是用户级线程,这样才能更有效地使用多个CPU。另外也需要有效地同步原子。操作系统的线程库必须提供所有的这些功能。
7.12 内存交换区
当操作系统因为没有足够的内存而将一些虚拟内存写到磁盘就会发生内存交换。内存交换对操作系统中运行的进程是透明的。只有操作系统知道特定的虚拟内存地址是在物理内存还是磁盘。
内存交换对MySQL性能影响是很糟糕的。它破坏了缓存在内存的目的,并且相对于使用很小的内存做缓存,使用交换区的性能更差。MySQL和存储引擎有很多算法来区别对待内存的数据和硬盘的数据,因为一般假设内存数据访问代价更低。