性能調優3:硬盤IO性能


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

內存和硬盤都是存儲資源和IO資源,木桶原理適用於SQL Server內部的資源爭用,資源的短板就是系統的瓶頸。由於內存的容量相對較小,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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM