你们都知道硬盘的随机IO很慢,可是比顺序IO慢多少呢,不知道你是否有过数字上的直接对比。今天我来实际压测对比一下磁盘在顺序IO和随机IO不一样场景下的性能数据表现。经过今天的实验数据,你将能深入理解数据库事务中为何要用日志的方式来实现,为何索引中要用节点更大的B+树。sql
对于任何存储系统,性能指标无非就是带宽、延迟或IOPS。个人测试机器的硬盘配置是一个由7块300G万起色械磁盘组成的RAID5,压测工具使用的fio,压测过程当中,咱们固定几个参数:数据库
而后再对另外的参数进行动态调整,而后进行屡次对比测试缓存
咱们先来看一下顺序读取状况下,在该磁盘阵列的带宽表现,见图1:性能优化
能够看到,当IO size比较小的时候,即便是顺序发起连续IO请求,带宽表现也不算给力,只有不到20MB/s。随着IO size增长的时候,带宽也上来了,最大可以达到1.2GB多。服务器
你们注意看下在NORA状况下,在128K增长到256K的时候,带宽忽然增长了不少,这是为啥呢?秘密在于个人RAID阵列里的条带大小是128K,当IO size为256K的时候,磁盘阵列才开始真正并行工做了。IO size小的时候,并不能发挥多盘优点。网络
/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -Lall -aALL ...... Strip Size : 128 KB
另外就是对于顺序IO的状况,RA预取也能起到一些做用,在IO size在64k的时候就可以达到1.2GB的带宽。工具
咱们再来看延迟,见图2:oop
咱们图中的单位是微秒-us,在《简单聊聊磁盘分区》中,我对磁盘耗时进行过理论上的估算,磁盘耗时主要在两个地方:性能
为何在图2实验结果里,延时却都很低,在IO size为512的时候,平均居然只有30us左右?其实顺序IO的状况下,RAID卡缓存命中率很高,其实绝大部分的读请求并无穿透到让磁盘的机械轴来工做。测试
咱们再来看IOPS,见图3:
在IO请求size正好为1个扇区大小的时候,磁盘阵列的IOPS表现最高,达到了3W屡次每秒。当IO size增长的时候,IOPS在逐步降低,但这时候,其实磁盘的吞吐是在增长的。
汇总一下,磁盘阵列在顺序IO的状况下表现仍是很不错的,缘由有三个:
咱们做为开发者使用磁盘的时候,可能不必定能保证永远都能让它工做在最舒服的状态,有些时候可能也必须得让它进行随机访问。因此咱们今天也试一下个人磁盘阵列在随机状况下的表现,对于fio工具来讲只须要设置rw参数为randread既可。不过IO size我只测试到了128就停了,由于再大了就越像顺序IO了。
咱们仍是先来看带宽,见图4:
机械硬盘即便是组成了RAID阵列,并且还有缓存,貌似对随机IO也迫不得已。在随机IO的状况下,带宽吞吐糟糕透了,在IO size比较小的时候,居然只有零点几兆每秒。
咱们再来看延时,见图5:
随机状况下延时基本都5ms左右,这就和咱们前面理论上的计算结果对上了。随机访问致使更多的请求真正穿透到了机械轴上。
再来看IOPS,这个指标也不好,也就是200左右吧。这个数据和图5的延迟造成了呼应,处理一次请求5ms左右,那么1秒可不就是只能处理200次左右么。因此硬盘厂家们每天给你吹风,说他家磁盘IOPS能达到几万几万。可是他们历来闭口不提随机IO状况下,其实特么的只有200。
你们看到了个人万起色械硬盘组成RAID5阵列,在顺序条件最好的状况下,带宽能够达到1GB/s以上,平均延时也很是低,最低只有20多us。可是在随机IO的状况下,机械硬盘的短板就充分暴露了,零点几兆的带宽,将近5ms的延迟,IOPS只有200左右。其缘由是由于
理解了磁盘顺序IO时候的几十M甚至一个GB的带宽,随机IO这个真的是太可怜了。
从上面的测试数据中咱们看到了机械硬盘在顺序IO和随机IO下的巨大性能差别。在顺序IO状况下,磁盘是最擅长的顺序IO,再加上Raid卡缓存命中率也高。这时带宽表现有几10、几百M,最好条件下甚至能达到1GB。IOPS这时候能有2-3W左右。 到了随机IO的情形下,机械轴也被逼的跳来跳去寻道,RAID卡缓存也失效了。带宽跌到了1MB如下,最低只有100K,IOPS也只有可怜巴巴的200左右。
若是你真正理解了以上实验中的数据,就能理解不少工程实践中的许多的事情。
复制文件夹:咱们都知道,在复制一个文件夹的时候,若是这个文件夹里面包含了许多堆碎文件,这时候复制起来很是慢。缘由就是这时候机械硬盘大几率都是在随机IO。怎么提升复制速度呢?很简单,就是把它们先打一个包。打包以后这个文件夹就变成一个大文件了,这时候再复制的话,磁盘就是执行的最擅长的顺序IO了,因此会快不少。
数据库事务:全部的数据库在实现事务的时候,都要保证写数据落盘成功才能返回。但为何他们几乎都是落盘到本身的事务日志文件里去就返回成功的,而不是直接写入到数据表文件里。这背后的缘由仍是磁盘读写性能问题,事务只须要保证数据落地成功就能够,至于写到哪里并不重要。写到数据文件中的话大几率就变成随机IO了。若是写到一个日志文件中,就是地地道道的顺序IO,性能就发挥到极致。
Mysql的B+树:在上面的数据中你们还能够看到,不管是顺序IO仍是随机IO,只要增长每次IO的单位,性能都会上涨。理解了这个,你就能真正理解为何Mysql是采用B+树当索引,而不是用其它的树了(好比二叉树)。由于B+树的节点更大,IO起来会让磁盘工做更舒服一些。
最后结尾我想分享一个5年前我在工程中实际性能优化的案例。当时接手了一个系统,要用数以百万级的用户imei,到Mysql中去查询用户的另外一个字符串id(clientid)数据。前开发的实现方式是传统的分批进行Mysql语句查询。这种实现下,且不说屡次的网络RTT耗时,单说Mysql查询,即便是有索引这时候也得须要进行大量的随机IO,由于用户imei是随机分布的。我采用的优化方式也很是简单,直接把Mysql用户整张用户表一次性经过顺序IO的方式读出来,load到内存中。在内存中用HashTable组织好,经过Hash的方式进行快速查询。最终耗时优化掉了90%以上。
开发内功修炼之硬盘篇专辑:
个人公众号是「开发内功修炼」,在这里我不是单纯介绍技术理论,也不仅介绍实践经验。而是把理论与实践结合起来,用实践加深对理论的理解、用理论提升你的技术实践能力。欢迎你来关注个人公众号,也请分享给你的好友~~~