你們都知道硬盤的隨機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%以上。
開發內功修煉之硬盤篇專輯:
個人公衆號是「開發內功修煉」,在這裏我不是單純介紹技術理論,也不僅介紹實踐經驗。而是把理論與實踐結合起來,用實踐加深對理論的理解、用理論提升你的技術實踐能力。歡迎你來關注個人公衆號,也請分享給你的好友~~~