天天看點

資料庫-IO系統性能之衡量性能的幾個名額

轉自http://storage.it168.com/a2011/0323/1169/000001169755_all.shtml

作為一個資料庫管理者,關注系統的性能是日常最重要的工作之一,而在所關注的各方面的性能隻能IO性能卻是最令人頭痛的一塊,面對着各種生澀的參數 和令人眼花缭亂的新奇的術語,再加上存儲廠商的忽悠,總是讓我們有種雲裡霧裡的感覺。本系列文章試圖從基本概念開始對磁盤存儲相關的各種概念進行綜合歸 納,讓大家能夠對IO性能相關的基本概念,IO性能的監控和調整有個比較全面的了解。

  在這一部分裡我們先舍棄各種結構複雜的存儲系統,直接研究一個單獨的磁盤的性能問題,藉此了解各個衡量IO系統系能的各個名額以及之間的關系。需要注意的是,本文探讨的僅限于磁盤IO性能,網絡IO性能不考慮在内。

  幾個基本的概念

  在研究磁盤性能之前我們必須先了解磁盤的結構,以及工作原理。不過在這裡就不再重複說明了,關系硬碟結構和工作原理的資訊可以參考維基百科上面的相關詞條——Hard disk drive(英文)和硬碟驅動器(中文)。

  讀寫IO(Read/Write IO)操作

  磁盤是用來給我們存取資料用的,是以當說到IO操作的時候,就會存在兩種相對應的操作,存資料時候對應的是寫IO操作,取資料的時候對應的是是讀IO操作。

  單個IO操作

  當控制磁盤的控制器接到作業系統的讀IO操作指令的時候,控制器就會給磁盤發出一個讀資料的指令,并同時将要讀取的資料塊的位址傳遞給磁盤,然後磁盤會将讀取到的資料傳給控制器,并由控制器傳回給作業系統, 完成一個寫IO的操作;同樣的,一個寫IO的操作也類似,控制器接到寫的IO操作的指令和要寫入的資料,并将其傳遞給磁盤,磁盤在資料寫入完成之後将操作 結果傳遞回控制器,再由控制器傳回給作業系統,完成一個寫IO的操作。單個IO操作指的就是完成一個寫IO或者是讀IO的操作。

  随機通路(Random Access)與連續通路(Sequential Access)

   随機通路指的是本次IO所給出的扇區位址和上次IO給出扇區位址相差比較大,這樣的話磁頭在兩次IO操作之間需要作比較大的移動動作才能重新開始讀/寫 資料。相反的,如果當次IO給出的扇區位址與上次IO結束的扇區位址一緻或者是接近的話,那磁頭就能很快的開始這次IO操作,這樣的多個IO操作稱為連續 通路。是以盡管相鄰的兩次IO操作在同一時刻發出,但如果它們的請求的扇區位址相差很大的話也隻能稱為随機通路,而非連續通路。

  順序IO模式(Queue Mode)/并發IO模式(Burst Mode)

  磁盤控制器可能會一次對磁盤組發出一連串的IO指令,如果磁盤組一次隻能執行一個IO指令時稱為順序IO;當磁盤組能同時執行多個IO指令時,稱為并發IO。并發IO隻能發生在由多個磁盤組成的磁盤組上,單塊磁盤隻能一次處理一個IO指令。

  單個IO的大小(IO Chunk Size)

   熟悉資料庫的人都會有這麼一個概念,那就是資料庫存儲有個基本的塊大小(Block Size),不管是SQL Server還是Oracle,預設的塊大小都是8KB,就是資料庫每次讀寫都是以8k為機關的。那麼對于資料庫應用發出的固定8k大小的單次讀寫到了寫 磁盤這個層面會是怎麼樣的呢,就是對于讀寫磁盤來說單個IO操作操作資料的大小是多少呢,是不是也是一個固定的值?

  答案是不确定。首先 作業系統為了提高 IO的性能而引入了檔案系統緩存(File System Cache),系統會根據請求資料的情況将多個來自IO的請求先放在緩存裡面,然後再一次性的送出給磁盤,也就是說對于資料庫發出的多個8K資料塊的讀操 作有可能放在一個磁盤讀IO裡就處理了。

  還有對于有些存儲系統也是提供了緩存(Cache)的,接收到作業系統的IO請求之後也是會将 多個作業系統的 IO請求合并成一個來處理。不管是作業系統層面的緩存還是磁盤控制器層面的緩存,目的都隻有一個,提高資料讀寫的效率。是以每次單獨的IO操作大小都是不 一樣的,它主要取決于系統對于資料讀寫效率的判斷。

  當一次IO操作大小比較小的時候我們成為小的IO操作,比如說1K,4K,8K這樣的;當一次IO操作的資料量比較的的時候稱為大IO操作,比如說32K,64K甚至更大。

  在我們說到塊大小(Block Size)的時候通常我們會接觸到多個類似的概念,像我們上面提到的那個在資料庫裡面的資料最小的管理機關,Oralce稱之為塊(Block),大小一般為8K,SQL Server稱之為頁(Page),一般大小也為8k。

   在檔案系統裡面我們也能碰到一個檔案系統的塊,在現在很多的Linux系統中都是4K(通過 /usr/bin/time -v可以看到),它的作用其實跟資料庫裡面的塊/頁是一樣的,都是為了友善資料的管理。但是說到單次IO的大小,跟這些塊的大小都是沒有直接關系的,在英 文裡單次IO大小通常被稱為是IO Chunk Size,不會說成是IO Block Size的。

  IOPS(IO per Second)

  IOPS,IO系統每秒所執行IO操作的次數,是一個重要的用來衡量系統IO能力的一個參數。對于單個磁盤組成的IO系統來說,計算它的IOPS不是一件很難的事情,隻要我們知道了系統完成一次IO所需要的時間的話我們就能推算出系統IOPS來。

  現在我們就來推算一下磁盤的IOPS,假設磁盤的轉速(Rotational Speed)為15K RPM,平均尋道時間為5ms,最大傳輸速率為40MB/s(這裡将讀寫速度視為一樣,實際會差别比較大)。

   對于磁盤來說一個完整的IO操作是這樣進行的:當控制器對磁盤發出一個IO操作指令的時候,磁盤的驅動臂(Actuator Arm)帶讀寫磁頭(Head)離開着陸區(Landing Zone,位于内圈沒有資料的區域),移動到要操作的初始資料塊所在的磁道(Track)的正上方,這個過程被稱為尋址(Seeking),對應消耗的時 間被稱為尋址時間(Seek Time);但是找到對應磁道還不能馬上讀取資料,這時候磁頭要等到磁盤盤片(Platter)旋轉到初始資料塊所在的扇區(Sector)落在讀寫磁頭正上方的之後才能開始讀取資料,在這個等待盤片旋 轉到可操作扇區的過程中消耗的時間稱為旋轉延時(Rotational Delay);接下來就随着盤片的旋轉,磁頭不斷的讀/寫相應的資料塊,直到完成這次IO所需要操作的全部資料,這個過程稱為資料傳送(Data Transfer),對應的時間稱為傳送時間(Transfer Time)。完成這三個步驟之後一次IO操作也就完成了。

  在我們看硬碟廠商的宣傳單的時候我們經常能看到3個參數,分别是平均尋址時間、盤片旋轉速度以及最大傳送速度,這三個參數就可以提供給我們計算上述三個步驟的時間。

   第一個尋址時間,考慮到被讀寫的資料可能在磁盤的任意一個磁道,既有可能在磁盤的最内圈(尋址時間最短),也可能在磁盤的最外圈(尋址時間最長),是以 在計算中我們隻考慮平均尋址時間,也就是磁盤參數中标明的那個平均尋址時間,這裡就采用目前最多的10krmp硬碟的5ms。

  第二個旋 轉延時,和尋址一樣,當磁頭定位到磁道之後有可能正好在要讀寫扇區之上,這時候是不需要額外額延時就可以立刻讀寫到資料,但是最壞的情況确實要磁盤旋轉整 整一圈之後磁頭才能讀取到資料,是以這裡我們也考慮的是平均旋轉延時,對于10krpm的磁盤就是(60s/15k)*(1/2) = 2ms。

   第三個傳送時間,磁盤參數提供我們的最大的傳輸速度,當然要達到這種速度是很有難度的,但是這個速度卻是磁盤純讀寫磁盤的速度,是以隻要給定了單次 IO的大小,我們就知道磁盤需要花費多少時間在資料傳送上,這個時間就是IO Chunk Size / Max Transfer Rate。

  IOPS計算公式

  現在我們就可以得出這樣的計算單次IO時間的公式:

  IO Time = Seek Time + 60 sec/Rotational Speed/2 + IO Chunk Size/Transfer Rate

  于是我們可以這樣計算出IOPS

  IOPS = 1/IO Time = 1/(Seek Time + 60 sec/Rotational Speed/2 + IO Chunk Size/Transfer Rate)

  對于給定不同的IO大小我們可以得出下面的一系列的資料

  4K (1/7.1 ms = 140 IOPS)

  5ms + (60sec/15000RPM/2) + 4K/40MB = 5 + 2 + 0.1 = 7.1

  8k (1/7.2 ms = 139 IOPS)

  5ms + (60sec/15000RPM/2) + 8K/40MB = 5 + 2 + 0.2 = 7.2

  16K (1/7.4 ms = 135 IOPS)

  5ms + (60sec/15000RPM/2) + 16K/40MB = 5 + 2 + 0.4 = 7.4

  32K (1/7.8 ms = 128 IOPS)

  5ms + (60sec/15000RPM/2) + 32K/40MB = 5 + 2 + 0.8 = 7.8

  64K (1/8.6 ms = 116 IOPS)

  5ms + (60sec/15000RPM/2) + 64K/40MB = 5 + 2 + 1.6 = 8.6

  從上面的資料可以看出,當單次IO越小的時候,單次IO所耗費的時間也越少,相應的IOPS也就越大。

   上面我們的資料都是在一個比較理想的假設下得出來的,這裡的理想的情況就是磁盤要花費平均大小的尋址時間和平均的旋轉延時,這個假設其實是比較符合我們 實際情況中的随機讀寫,在随機讀寫中,每次IO操作的尋址時間和旋轉延時都不能忽略不計,有了這兩個時間的存在也就限制了IOPS的大小。現在我們考慮一 種相對極端的順序讀寫操作,比如說在讀取一個很大的存儲連續分布在磁盤的的檔案,因為檔案的存儲的分布是連續的,磁頭在完成一個讀IO操作之後,不需要從 新的尋址,也不需要旋轉延時,在這種情況下我們能到一個很大的IOPS值,如下

  4K (1/0.1 ms = 10000 IOPS)

  0ms + 0ms + 4K/40MB = 0.1

  8k (1/0.2 ms = 5000 IOPS)

  0ms + 0ms + 8K/40MB = 0.2

  16K (1/0.4 ms = 2500 IOPS)

  0ms + 0ms + 16K/40MB = 0.4

  32K (1/0.8 ms = 1250 IOPS)

  0ms + 0ms + 32K/40MB = 0.8

  64K (1/1.6 ms = 625 IOPS)

  0ms + 0ms + 64K/40MB = 1.6

  相比第一組資料來說差距是非常的大的,是以當我們要用IOPS來衡量一個IO系統的系能的時候我們一定要說清楚是在什麼情況的IOPS,也就是要說明讀寫的方式以及單次IO的大小,當然在實際當中,特别是在OLTP的系統的,随機的小IO的讀寫是最有說服力的。

  傳輸速度(Transfer Rate)/吞吐率(Throughput)

  現在我們要說的傳輸速度(另一個常見的說法是吞吐率)不是磁盤上所表明的最大傳輸速度或者說理想傳輸速度,而是磁盤在實際使用的時候從磁盤系統總線上流過的資料量。有了IOPS資料之後我們是很容易就能計算出對應的傳輸速度來的

  Transfer Rate = IOPS * IO Chunk Size

  還是那上面的第一組IOPS的資料我們可以得出相應的傳輸速度如下

  4K: 140 * 4K = 560K / 40M = 1.36%

  8K: 139 * 8K = 1112K / 40M = 2.71%

  16K: 135 * 16K = 2160K / 40M = 5.27%

  32K: 116 * 32K = 3712K / 40M = 9.06%

  可以看出實際上的傳輸速度是很小的,對總線的使用率也是非常的小。

   這裡一定要明确一個概念,那就是盡管上面我們使用IOPS來計算傳輸速度,但是實際上傳輸速度和IOPS是沒有直接關系,在沒有緩存的情況下它們共同的 決定因素都是對磁盤系統的通路方式以及單個IO的大小。對磁盤進行随機通路時候我們可以利用IOPS來衡量一個磁盤系統的性能,此時的傳輸速度不會太大; 但是當對磁盤進行連續通路時,此時的IOPS已經沒有了參考的價值,這個時候限制實際傳輸速度卻是磁盤的最大傳輸速度。是以在實際的應用當中,隻會用 IOPS來衡量小IO的随機讀寫的性能,而當要衡量大IO連續讀寫的性能的時候就要采用傳輸速度而不能是IOPS了。

  IO響應時間(IO Response Time)

   最後來關注一下能直接描述IO性能的IO響應時間。IO響應時間也被稱為IO延時(IO Latency),IO響應時間就是從作業系統核心發出的一個讀或者寫的IO指令到作業系統核心接收到IO回應的時間,注意不要和單個IO時間混淆了,單 個IO時間僅僅指的是IO操作在磁盤内部處理的時間,而IO響應時間還要包括IO操作在IO等待隊列中所花費的等待時間。

  計算IO操作 在等待隊列裡面消耗的時間有一個衍生于利托氏定理(Little’s Law)的排隊模型M/M/1模型可以遵循,由于排隊模型算法比較複雜,到現在還沒有搞太明白(如果有誰對M/M/1模型比較精通的話歡迎給予指導),這 裡就羅列一下最後的結果,還是那上面計算的IOPS資料來說:

  8K IO Chunk Size (135 IOPS, 7.2 ms)

  135 => 240.0 ms

  105 => 29.5 ms

  75 => 15.7 ms

  45 => 10.6 ms

  64K IO Chunk Size(116 IOPS, 8.6 ms)

  135 => 沒響應了……

  105 => 88.6 ms

  75 => 24.6 ms

  45 => 14.6 ms

   從上面的資料可以看出,随着系統實際IOPS越接近理論的最大值,IO的響應時間會成非線性的增長,越是接近最大值,響應時間就變得越大,而且會比預期 超出很多。一般來說在實際的應用中有一個70%的指導值,也就是說在IO讀寫的隊列中,當隊列大小小于最大IOPS的70%的時候,IO的響應時間增加會 很小,相對來說讓人比較能接受的,一旦超過70%,響應時間就會戲劇性的暴增,是以當一個系統的IO壓力超出最大可承受壓力的70%的時候就是必須要考慮 調整或更新了。

  另外補充說一下這個70%的指導值也适用于CPU響應時間,這也是在實踐中證明過的,一旦CPU超過70%,系統将會變得受不了的慢。很有意思的東西。