1. 程式人生 > >效能調優3:硬碟IO效能

效能調優3:硬碟IO效能

資料庫系統嚴重依賴伺服器的資源:CPU,記憶體和硬碟IO,通常情況下,記憶體是資料的讀寫效能最高的儲存介質,但是,記憶體的價格昂貴,這使得系統能夠配置的記憶體容量受到限制,不能大規模用於資料儲存;並且記憶體是易失性的,不能持久化儲存資料,這使得記憶體只能作為執行時的快取記憶體,而硬碟是永久儲存資料的理想介質,價格低廉,在系統停電時,能夠保持資料不丟失。但是,硬碟是低速的儲存介質,輸入和輸出(IO)速度比記憶體低很多。因此,在實際執行的資料庫系統中,相對於記憶體而言,硬碟的IO有更大可能性成為系統性能的瓶頸。

記憶體和硬碟都是儲存資源和IO資源,由於記憶體的容量相對較小,IO速度快,因此,記憶體更有可能成為爭用的儲存資源;而硬碟容量大,IO速度快,因此,硬碟更有可能成為系統爭用IO資源。SQL Server為了平衡儲存和IO資源的爭用,在把資料從硬碟讀取到記憶體後,會把資料快取到記憶體中,當重複訪問資料時,不需要從硬碟,而是直接從記憶體中獲取。由於這個機制,為系統配置

足夠多的記憶體可以最小化硬碟IO,因為硬碟讀取資料的速度遠遠低於記憶體,所以,儘可能減少硬碟IO可以在很大程度上提供系統的效能。

一,硬碟IO的延時

對於SQL Server資料庫系統,限制查詢響應的主要因素是硬碟的延時,根據硬碟的物理構造(磁軌和扇區),延時可以分為尋道延時和旋轉延時:

  • 尋道延時:硬碟的物理刺頭移動並定位到所需資料的時間,
  • 旋轉延時:硬碟旋轉到所需資料的時間,通常用MB/S,或IO吞吐量來衡量

在OLTP系統中,資料更新操作較多,每次讀取的資料量少,目標資料的位置相對隨機(隨機讀寫),因此,對於尋道延時要求更高,硬碟需要花費更多的尋道時間。

在DSS/DW系統中,事務的執行時間更長,資料相對靜態,不常更新,讀操作比寫操作的要求更高,順序讀操作佔比很高,因此,IO吞吐量更重要,可以通過硬碟的盤面來增加順序訪問的IO吞吐量。

二,根據WaitType偵測IO效能

SQL Server引擎把IO作為一個資源來看待,在多工的現代資料庫系統中,同一時刻會接收到很多查詢請求,每一個查詢請求都需要申請系統資源(CPU、記憶體和IO),才能繼續執行下去,然而系統的資源是有限的,當查詢爭用資源時,有些查詢請求資源得到滿足,順利執行下去,有些查詢請求的資源得不到滿足,該查詢就被阻塞,處於等待資源分配的狀態。當出現IO效能問題時,查詢語句會被硬碟IO阻塞,這使得執行計劃被迫掛起(或阻塞)來等待資源,SQL Server通過DMV來顯示系統執行的狀態,用等待型別來表示不同的阻塞資訊。

1,資料檔案的IO

如果SQL Server 出現 IO 效能問題,那麼在SQL Server 內部通過DMV sys.dm_exec_requests的wait_type,來反饋 IO 問題。如果查詢請求的wait_type長時間處於PageIOLatch_XX,那麼說明系統不能很快把資料讀取到記憶體中。

PAGEIOLATCH_xx :用於描述資料頁的IO爭用,說明系統正在從硬碟載入資料到記憶體的Buffer Pool中

當SQL Server 要去讀或寫一個Page的時候,首先會在Buffer Pool裡尋找,如果在Buffer Pool中找到了,那麼讀寫操作會繼續進行,沒有任何等待。如果沒有找到,那麼SQL Server 就會設定Wait_Type為PageIOLatch_EX(寫)或PageIOLatch_SH(讀),然後發起一個非同步IO操作,將頁面讀入Buffer Pool中,在IO沒有完成之前,Request將會保持在PageIOLatch_EX(寫)或PageIOLatch_SH(讀)的等待狀態。IO消耗的時間越長,等待的時間越長。

2,日誌檔案的寫入

日誌檔案以寫為主,工作量由修改命令激發的事務數量決定。當SQL Server要寫事務到日誌檔案時,如果Disk 不能及時完成IO請求,那麼事務就無法提交,SQL Server 不得不進入WriteLog 等待狀態,直到事務被成功記錄到日誌檔案中,才會提交當前的事務。

如果request經常出現WriteLog的Wait type,說明事務日誌的寫請求不能被Disk及時完成,這種情況,對SQL Server 整體效能影響較大。

WRITELOG:在資料被修改時,在Log Cache和Buffer Cache中都會有記錄,如果在Log Cache中的資料在checkpoint時寫入硬碟,就會發生這種等待。

LOGBUFFER等待:很少出現,當一個任務正在等待儲存日誌到Log Buffer中時,就會出現LOGBUFFER等待,出現這種等待,說明日誌所在的硬碟無法響應請求。如果把日誌檔案放在一個非常慢的硬碟上,而資料檔案放在一個非常快的硬碟上,就會出現這種等待。

3,AYSNC_IO_COMPLIETION和IO_COMPLIETION也是IO瓶頸的潛在指標

  • AYSNC_IO_COMPLIETION:標識任務正在等待IO請求來完成操作,當一個應用程式連線SQL Server,在處理資料時變得非常慢,很可能就會出現這種型別的等待。
  • IO_COMPLIETION:發生在一個任務正在等待用於非資料頁IO的IO操作上,非資料頁,一般是指日誌檔案,通常發生在修改大量修改,或者記憶體中存在大量的髒資料時。

三,影響讀寫效能的因素

資料庫系統對IO的效能依賴較高,那麼影響資料庫系統讀寫效能的因素有哪些呢?

1,物理硬碟的IO能力

機械硬碟的IO速度沒有固態硬碟快,可以考慮把資料庫系統的機械硬碟更新為固態硬碟。

2,記憶體對硬碟IO的影響

在SQL Server Engine 訪問資料時,如果相應的data不存在於Buffer Pool,那麼Buffer Manager 從Disk中的Data File(mdf 或 ndf)中將相應的data page讀取到記憶體中。SQL Server 將data page快取起來。理想情況下,只要SQL Server能夠使用的記憶體充足,SQL Server 會將所有讀取到記憶體的中Data Page快取到Buffer Pool中。對於讀取操作,只要相應的資料都快取在記憶體中,Select 就不會有任何硬碟IO。

當Buffer Pool空間不足時,SQL Server 啟用 LazyWriter,主動將記憶體中一些很久沒有使用的Data Cache和 Plan Cache 清除,mark為Free buffer,供其它Data Page使用。如果這些Page上的修改還沒有被CheckPoint寫回Disk,那麼LazyWrite會將其寫回。

3,碎片和壓縮

如果資料頁面或index 頁面的碎片很多,每個頁面儲存的資料行較少,那麼SQL Server 需要讀寫更多的Page。如果資料在頁面裡儲存的非常緊湊,儲存相同資料所消耗的Page越少,並且可以充分利用SQL Server 預讀的優勢,減少IO。

壓縮技術不僅使資料佔用的Disk 空間減少,而且能夠減少IO。由於資料在寫入Disk之間經過壓縮處理,儲存相同資料所消耗的Page減少,讀取的Data Page會減少。壓縮技術在一定程度上能夠降低IO,但需要付出一定的代價:額外消耗少量的CPU和記憶體來解壓縮。

4,利用多個物理硬碟實現Data File的併發讀寫

在DB中的FileGroup 建立多個File,將這些File存放到不同的Physical Disk上。File 分佈到不同的Physical Disk上,IO也會分佈到不同的Physical Disk上,這樣能夠實現資料的併發讀取,提高讀取效能。

對於日誌檔案,SQL Server會頻繁的寫事務日誌。只要資料庫發生修改,就會不斷地寫入日誌檔案。如果不能及時完成日誌檔案的IO,會導致事務的延遲提交,對效能的影響較大,所以,儘量將日誌檔案放到寫入速度快的Disk上。SQL Server 順序寫事務日誌,在一個時間點,SQL Server 只會寫一個日誌檔案。在不同的Physical Disk上建立多個log file對效能基本沒有幫助。

5,工作負載

日誌檔案以寫為主,工作量由修改命令申請的事務數量決定,日誌檔案是順序寫的,寫入速度快於隨機寫。如果日誌記錄不能及時寫入,那麼Request會處於WriteLog等待狀態,對系統整體效能影響較大。

資料檔案寫入的資料量由修改量決定,SQL Server除了設定bulk logged 恢復模式之外,沒有太大的調整選項。

資料檔案讀取的資料量,由訪問的資料量和Buffer Pool中快取的資料量共同決定。如果訪問的資料量減少或者記憶體快取區增加,都可以降低SQL Server 從Physical Disk讀取的Data Page數量。在記憶體不變的情況下,可以通過優化查詢語句,減少資料訪問量,來提高SQL Server 資料檔案的讀取效能。

四,硬碟IO的效能優化

硬碟IO的效能調優,通常來說,跟Buffer Pool的大小和資料的分佈有關

1, Buffer Pool

Buffer Pool是SQL Server資料庫系統的緩衝池,用於快取從硬碟讀取的資料頁。當SQL Server所需的資料不在記憶體的Buffer Pool中時,就會觸發硬碟IO,把資料從硬碟中的檔案中讀取到記憶體中的Buffer Pool中。如果所需的資料存在於Buffer Pool中,SQL Server直接從記憶體中獲取資料,不會觸發任何硬碟的IO操作。因此,記憶體容量足夠大,硬碟IO將會足夠小。如果系統存在記憶體壓力,那麼SQL Server將會頻繁地觸發硬碟IO,從硬碟檔案中獲取資料,這將會增加查詢的響應時間。

2, 多硬碟併發IO

在儲存資料時,把資料分佈在不同的物理硬碟上,在讀寫資料時,可以把工作負載分擔到不同的物理硬碟上,多個硬碟併發處理資料,將會大大降低資料的讀寫時間。

因此,在設計資料庫系統時,應該儘量把資料分佈到不同的物理硬碟上,並且每個硬碟上的資料量保持均衡,這樣,才能最大化利用多硬碟的優勢,實現資料的讀寫時間最小化。

3,日誌檔案

當修改資料時,事務會被記錄到日誌檔案中,事務日誌的寫入速度,直接影響了資料更新查詢語句的執行效率。當資料庫中存在大量的修改操作時,應該把日誌檔案儲存到IO效能最優的硬碟上,以減少日誌檔案寫入的時間延遲。

4,tempdb資料庫檔案

tempdb是資料庫例項中最繁忙的資料庫了,在查詢語句執行的過程中,查詢語句建立的各種臨時表,系統建立的中間表都位於tempdb中,tempdb的資料檔案和日誌檔案的讀寫效能,直接影響了查詢語句的執行時間,應該把tempdb資料庫的資料檔案部分到不同的物理硬碟中,並且把tempdb的日誌檔案存放到IO效能最優的硬碟上去。

簡而言之,對於資料庫系統的優化配置是:

  • 在OLTP系統中,合理的配置是把資料檔案,日誌檔案和tempdb的檔案分別存放到不同的物理硬碟上,從而分攤硬碟的IO爭用。
  • 在OLAP系統中,事務執行時間長,規模大,資料相對靜態,每次返回的資料量較大,對IO吞吐量的要求較高,因此,儘可能分攤硬碟的IO爭用。

5,建立合適的索引

如果一個查詢需要進行表掃描,一般是因為缺失合適的索引或索引統計資訊過時,過多的掃描操作會引起記憶體不足,使得快取中的資料或執行計劃被清除(或者被轉移到硬碟),然後從硬碟載入資料到記憶體。理想情況下,常用的資料應該儘可能久地駐留在記憶體中,避免不必要的記憶體活動。

建立合適的索引,並保證統計資訊及時更新,能夠避免不必要的表掃描,只加載小的資料集,能夠減少IO操作的次數,優化IO效能。

6,資料壓縮

資料壓縮會使得相同的儲存空間能夠儲存更多的資料量,一次IO操作能夠載入更多的資料,這也能減少IO操作的次數,優化IO效能。

五,IO統計

IO請求的等待和掛起,資料庫引擎記錄對資料檔案和日誌檔案的IO操作,快取到函式:sys.dm_io_virtual_file_stats,對於資料檔案,資料的物理讀操作更為重要;對於日誌檔案,資料的讀寫操作都重要:

  • io_stall_read_ms:等待讀操作的時間
  • io_stall_write_ms:等待寫操作的時間

如果硬碟繁忙,資料庫引擎傳送的IO請求,可能會被IO子系統掛起(pending),資料庫引擎把pending的IO請求快取到檢視:sys.dm_io_pending_io_requests,

  • io_pending:指定是否有IO請求掛起或完成

1,檢視資料庫檔案的IO和等待IO完成的時間

select db_name(vfs.database_id) as db_name,
    --vfs.file_id,
    mf.name as file_name,
    mf.type_desc as file_type,
    vfs.sample_ms/1000/60/60 as sample_h,
    vfs.io_stall_read_ms/vfs.num_of_reads as avg_stall_read_ms,
    vfs.io_stall_write_ms/vfs.num_of_writes as avg_stall_write_ms,

    vfs.num_of_reads as physical_reads,
    vfs.num_of_bytes_read/vfs.num_of_reads/1024 as avg_read_kb,
    vfs.num_of_writes as physical_writes,
    vfs.num_of_bytes_written/vfs.num_of_writes/1024 as avg_written_kb,
    cast(vfs.size_on_disk_bytes/1024/1024/1024.0 as decimal(10,2)) as disk_size_gb,
    --cast(mf.size/1024*8/1024.0 as decimal(10,2)) as file_size_gb,
    vfs.file_handle
from sys.master_files mf 
cross apply sys.dm_io_virtual_file_stats(mf.database_id,mf.file_id) as vfs
where mf.database_id=db_id()  --current db
order by avg_stall_read_ms desc ,avg_stall_write_ms desc

2,檢視pending的IO請求

select db_name(vfs.database_id) as db_name,
    --vfs.file_id,
    mf.name as file_name,
    pr.io_type,
    sum(pr.io_pending_ms_ticks) as io_pending_ms,
    pr.io_pending
from sys.dm_io_virtual_file_stats(null,null) vfs
inner join sys.dm_io_pending_io_requests as pr
    on vfs.file_handle=pr.io_handle
inner join sys.master_files mf
    on vfs.database_id=mf.database_id
        and vfs.file_id=mf.file_id
group by vfs.database_id,
    mf.file_id,
    mf.name,
    pr.io_type,
    pr.io_pending
order by vfs.database_id,
    mf.name

3,計劃快取中的邏輯寫排名

select 
    p.name as sp_name
    ,s.total_logical_reads
    ,s.total_logical_writes
    ,s.total_physical_reads
    ,s.total_elapsed_time
    ,s.total_worker_time
    ,s.cached_time
    ,s.execution_count
    ,s.type
    ,s.type_desc
from sys.procedures p
inner join sys.dm_exec_procedure_stats s
    on p.object_id=s.object_id
where s.database_id=DB_ID()
    and s.total_logical_writes>0
order by s.total_logical_writes

 

參考文件:

Windows Performance Monitor Disk Counters Explained

High Avg Disk Queue Length and finding the Cause

Disk Queue Length vs. Disk Latency Times: Which is Best for Measuring Database Performance