1. 程式人生 > >T-SQL執行內幕(10)——讀取資料

T-SQL執行內幕(10)——讀取資料

本文屬於SQL Server T-SQL執行內幕系列


    關係型資料庫的資料訪問操作總是從記憶體的快取中讀取資料而不是從磁碟中讀取。這個快取稱為Buffer Pool。如果資料訪問操作符未能在快取中找到所需的資料,那麼就需要從磁碟中載入,這就會產生一個磁碟I/O讀(set statistics io on中的物理讀),並且需要等待這個物理讀完成(及從磁碟找到資料並載入到快取為止)之後,才能進行操作。在Buffer Pool中的資料是共享給所有查詢以便更高效地使用資源和降低不必要的I/O請求。

    SQL Server會盡可能多地讀取資料到快取中,直到系統中所有記憶體分配給SQL Server(通過修改最大伺服器記憶體限制來控制),才會增加分配給私有記憶體的程序。資料快取是SQL Server佔用記憶體的最大部分,熱資料的快取能夠極大地降低資料訪問和檢索速度從而提高效能,所以千萬別再說SQL Server吃記憶體,伺服器那麼多的記憶體放在那裡幹嘛?注意I/O讀寫操作並不作用在單獨的行而是以8KB頁為操作單位。

堆操作

    首先來看看堆表上的讀取操作。在堆上進行掃描操作(注意堆只有掃描操作)的過程:

  1. 第一次呼叫next()時,操作符需要找到第一行然後返回。SQL Server儲存關於表的元資料用於描述哪個頁屬於這個表。管理物件使用的空間Inside the Storage Engine: IAM pages, IAM chains, and allocation units。資料訪問操作符會對緩衝池中的頁請求一個引用,返回指向所請求頁的記憶體中的副本指標。如果頁不在記憶體中,那麼請求會被阻塞直到頁從磁碟載入到記憶體為止。頁中包含了每個資料記錄的一個數組(偏移量)。這個資料記錄不一定是完整的一行,因為有LOB值和變長值存在,可能需要儲存在另外的頁,參考
    Inside the Storage Engine: Anatomy of a record
    。資料訪問操作符會定位頁中第一行,複製出請求所需的列值然後返回。同時會儲存一個內部狀態用於高效地回到這個位置。
  2. 父操作符處理操作符返回的第一行資料
  3. 當操作符再次呼叫next()方法時,會使用前面建立的上下文狀態去快速找到當前頁和行,然後按前面的方式處理下一行。
  4. 父操作符同樣處理子操作符返回的下一行資料。
  5. 這種操作直到屬於這個表的最後一個頁的最後一行被處理完為止。同時它的內部狀態會標識“超出表的尾部”,不能再返回任何行。
  6. 當資料訪問操作符不能在返回任何資料給父操作符時,父操作符就開始做自己需要操作的事情,比如一個SORT操作符現在就可以開始返回資料。
  7. 資料操作符可以後退(rewind),比如,如果堆掃描操作是巢狀迴圈操作中的內表,當完成時,父巢狀迴圈將請求外表的下一行,然後後退到資料訪問操作符(內表)並再次迴圈。後退將導致重置內部位置狀態,並使其從第一頁的第一行重新開始。

 B-Tree操作

    對於B-Tree結構的資料訪問操作:

  1. 第一次呼叫next()方法時,操作符必須找到第一行基於鍵請求的資料並返回。SQL Server 儲存關於B-Tree的元資料用於描述那個頁屬於這個索引,但是和堆表不同,堆表必須從第一頁開始,而B-Tree可以直接定位到特定的鍵。從元資料中查詢跟節點頁的ID然後請求Buffer Pool中這個頁的指標。使用查詢鍵值,資料訪問操作符定位B-Tree中包含第一行等於鍵值或者大於搜尋鍵值的葉子頁。在這個過程中,每一步都需要從BufferPool中找到對應的頁,一旦沒有找到,也會發生磁碟載入到記憶體的情況。在葉子頁中,資料訪問操作符通過預期的鍵值搜尋頁中的行,並且複製所需的資料然後返回。不過也存在找不到符合鍵值的行。由於B-Tree不僅可以定位行,還能找到大於鍵值的資料,所以B-Tree可以雙向查詢,這個“大於”依賴於鍵的定義。這個跟索引定義中的升序或降序不一樣,索引定義中的順序是B-Tree的行的實際順序。
  2. 父操作符處理子操作符返回的結果。
  3. 如果操作符使用範圍掃描,那麼next()方法會被再次呼叫用於查詢在前面資料的後面的值並返回。B-Tree訪問操作符會儲存前面返回的值的鍵值並用於定位,同時使用相同的過程來返回下一頁的第一行符合要求的資料。
  4. 父操作符繼續處理返回結果。
  5. 範圍掃描包含了範圍鍵值的尾部,再次呼叫next()方法時,如果行被移到高於範圍值尾部的地方。則會返回false。B-Tree中的高於包含了升序或排序。
  6. 對於rewind,B-Tree同樣可以重綁。倒帶復位操作員狀態, 以使用相同的鍵/範圍引數重新啟動查詢/掃描。重新繫結將更改實際的鍵值。
  7. 擴充套件內容可見:Showplan 邏輯運算子和物理運算子參考

總結

    從兩類操作可見,對於資料讀取,都是從快取中通過元資料的記錄去查詢資料,並且以遞迴迴圈的方式遍歷。