邏輯讀、物理讀、預讀的理解


  通過以下語句清楚數據緩存並開啟IO統計:

/****** 生產環境不可亂用 ******/
DBCC DROPCLEANBUFFERS; --清除緩存
SET STATISTICS IO ON; --開啟IO統計
SELECT * FROM FoodCorp;

  示例:

  

一、相關定義

  SQL SERVER 數據庫引擎當遇到一個查詢語句時,SQL SERVER數據庫引擎會分別生成執行計划(占用CPU和內存資源),同時存儲引擎讀取 IAM 以生成必須要讀取的磁盤地址排序列表。這使 SQL Server 得以將其 I/O 優化為大型有序讀取,根據它們在磁盤上的位置按順序完成。磁盤中取得需要取的數據(占用I/O資源,這就是預讀),注意,兩個步驟是並行的,SQL SERVER通過這種方式可以讓計算和 I/O 重疊進行,從而充分利用 CPU 和磁盤,從而提高性能。

  掃描計數:查詢數據時對涉及到的表被訪問次數或涉及到的索引的掃描次數。對於查詢中不包括連接命令時,這一信息並不是十分有用,但如果查詢中包含有一個或多個連接,則十分有用。
  一個循環外部的表的掃描計數值為1,但對於一個循環內的表而言,其值為循環的次數。可以想象得到,對於一個循環內的表而言,其掃描計數值越小,它所使用的資源越少,查詢的性能也就越高。因此在調節一個帶連接的查詢的性能時,需要關注掃描計數的值,在進行調節時,注意觀察它是增加還是減少了。
  邏輯讀: 這是SET STATISTICS IO或SET STATISTICS TIME命令提供的最有用的數據。SQL Server在對任何數據進行操作前,必須首先從磁盤中讀取數據所在的數據頁或索引頁,並把數據頁或索引頁存到數據緩沖區高速緩存中。
  邏輯讀是指SQL Server為得到查詢中的結果而必須從數據緩沖區高速緩存讀取的頁數。在執行查詢時,SQL Server不會讀取比實際需求多或少的數據, 因此,當在相同的數據集上執行同一個查詢,得到的邏輯讀的數字總是相同的。
  在每次執行同一查詢時,這個數值是不會變化的。因此,在進行查詢性能的調節時,這是一個可以用來衡量你的調節措施是否成功的一個很好的標准。
  在對查詢的性能進行調節時,如果邏輯讀值下降,就表明查詢使用的服務器資源減少,查詢的性能有所提高。如果邏輯讀值增加,則表示調節措施降低了查詢的性能。在其他條件不變的情況下,一個查詢使用的邏輯讀越少,其效率就越高,查詢的速度就越快。
  物理讀:指的是,在執行真正的查詢操作前,SQL Server必須從磁盤上向數據緩沖區高速緩存中讀取它所需要的數據。在SQL Server開始執行查詢前,它要作的第一件事就是檢查它所需要的數據是否在數據緩沖區高速緩存中,如果在,就從中讀取,如果不在,SQL Server必須首先將它需要的數據從磁盤上讀到數據緩沖區高速緩存中。
  SQL Server在執行物理讀時比執行邏輯讀需要更多的服務器資源。因此,在理想情況下,我們應當盡量避免物理讀操作。
  在對查詢的性能進行調節時,可以忽略物理讀而只專注於邏輯讀。SQL Server在執行查詢時所需要的物理讀次數不可能通過性能調節而減少的。減少物理讀的次數是DBA的一項重要工作,但它涉及到整個服務器性能的調節,而不僅僅是查詢性能的調節。在進行查詢性能調節時,我們不能控制數據緩沖區高速緩存的大小或服務器的忙碌程度以及完成查詢所需要的數據是在數據緩沖區中還是在磁盤上,唯一我們能夠控制的數據是得到查詢結果所需要執行的邏輯讀的次數。
  減少物理讀次數、加快SQL Server運行速度的一種方式是確保服務器的物理內存足夠多。
  預讀:預讀表示SQL Server在執行預讀機制時從磁盤上讀取的數據頁或索引頁。為了優化其性能,SQL Server數據引擎首先預測執行查詢執行計划所需的數據和索引頁,然后在查詢實際使用這些頁之前將它們讀入緩沖區高速緩存。根據SQL Server對數據需求預測的准確程度,預讀的數據頁可能有用,也可能沒用。與物理讀一樣,這個值在查詢性能調節中也沒有什么用處。

  注意:一個緩沖區就是一個 8KB 大小的內存頁

二、分析

  SQL SERVER數據存儲的方式:存儲的最小單位為頁(Page).每一頁大小為8k,SQL SERVER對於頁的讀取是原子性,要么讀完一頁,要么完全不讀,不會有中間狀態。而頁之間的數據組織結構為B樹。所以SQL SERVER對於邏輯讀,預讀,和物理讀的單位是頁。

  SQL SERVER一頁的總大小為:8K

      頁存儲的數據為:8192字節-96字節(頁頭)-36字節(行偏移)=8060字節

      所以每一頁用於存儲的實際大小為8060字節。

      通過表屬性→存儲,看到這個表的數據空間為5.336M:

  

  可以通過公式大概推算出占用了多少頁:

  5.336*1024*1024/8060(每頁的數據容量)≈ 694 - 表中非數據占用的空間 ≈687(邏輯讀取數)

   SQL SERVER查詢執行的步驟如果從微觀來看,那將會非常多。這里為了講述邏輯讀等概念,從比較高的抽象層次來看:

  

  當遇到一個查詢語句時,SQL SERVER會走第一步,分別為生成執行計划(占用CPU和內存資源),同步的用估計的數據去磁盤中取得需要取的數據(占用IO資源,這就是預讀),注意,兩個第一步是並行的,SQL SERVER通過這種方式來提高查詢性能。

      然后查詢計划生成好了以后去緩存讀取數據.當發現緩存缺少所需要的數據后讓緩存再次去讀硬盤(物理讀)。

      最后從緩存中取出所有數據(邏輯讀)。

  示例中的“ 預讀703次 ”即為估計的頁數,可以通過這個DMV看到該數據:

SELECT page_count
FROM sys.dm_db_index_physical_stats(DB_ID('foodtrace_fwq'),OBJECT_ID('FoodCorp'),NULL,NULL,'sampled')

  

  當我們第一次查詢完成后,再次進行查詢時,所有請求的數據這時已經在緩存中,SQL SERVER這時只要對緩存進行讀取就行了,也就是只用進行邏輯讀。

  

 


免責聲明!

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



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