關係型資料庫的資料訪問操作總是從記憶體的快取中讀取資料而不是從磁碟中讀取。這個快取稱為buffer pool。如果資料訪問操作符未能在快取中找到所需的資料,那麼就需要從磁碟中載入,這就會產生乙個磁碟i/o讀(set statistics io on中的物理讀),並且需要等待這個物理讀完成(及從磁碟找到資料並載入到快取為止)之後,才能進行操作。在buffer pool中的資料是共享給所有查詢以便更高效地使用資源和降低不必要的i/o請求。
sql server會盡可能多地讀取資料到快取中,直到系統中所有記憶體分配給sql server(通過修改最大伺服器記憶體限制來控制),才會增加分配給私有記憶體的程序。資料快取是sql server占用記憶體的最大部分,熱資料的快取能夠極大地降低資料訪問和檢索速度從而提高效能,所以千萬別再說sql server吃記憶體,伺服器那麼多的記憶體放在那裡幹嘛?注意i/o讀寫操作並不作用在單獨的行而是以8kb頁為操作單位。
首先來看看堆表上的讀取操作。在堆上進行掃瞄操作(注意堆只有掃瞄操作)的過程:
第一次呼叫next()時,操作符需要找到第一行然後返回。sql server儲存關於表的元資料用於描述哪個頁屬於這個表。管理物件使用的空間和inside the storage engine: iam pages, iam chains, and allocation units。資料訪問操作符會對緩衝池中的頁請求乙個引用,返回指向所請求頁的記憶體中的副本指標。如果頁不在記憶體中,那麼請求會被阻塞直到頁從磁碟載入到記憶體為止。頁中包含了每個資料記錄的乙個陣列(偏移量)。這個資料記錄不一定是完整的一行,因為有lob值和變長值存在,可能需要儲存在另外的頁,參考inside the storage engine: anatomy of a record。資料訪問操作符會定位頁中第一行,複製出請求所需的列值然後返回。同時會儲存乙個內部狀態用於高效地回到這個位置。
父操作符處理操作符返回的第一行資料
當操作符再次呼叫next()方法時,會使用前面建立的上下文狀態去快速找到當前頁和行,然後按前面的方式處理下一行。
父操作符同樣處理子操作符返回的下一行資料。
這種操作直到屬於這個表的最後乙個頁的最後一行被處理完為止。同時它的內部狀態會標識「超出表的尾部」,不能再返回任何行。
當資料訪問操作符不能在返回任何資料給父操作符時,父操作符就開始做自己需要操作的事情,比如乙個sort操作符現在就可以開始返回資料。
資料操作符可以後退(rewind),比如,如果堆掃瞄操作是巢狀迴圈操作中的內錶,當完成時,父巢狀迴圈將請求外表的下一行,然後後退到資料訪問操作符(內錶)並再次迴圈。後退將導致重置內部位置狀態,並使其從第一頁的第一行重新開始。
對於b-tree結構的資料訪問操作:
第一次呼叫next()方法時,操作符必須找到第一行基於鍵請求的資料並返回。sql server 儲存關於b-tree的元資料用於描述那個頁屬於這個索引,但是和堆表不同,堆表必須從第一頁開始,而b-tree可以直接定位到特定的鍵。從元資料中查詢跟節點頁的id然後請求buffer pool中這個頁的指標。使用查詢鍵值,資料訪問操作符定位b-tree中包含第一行等於鍵值或者大於搜尋鍵值的葉子頁。在這個過程中,每一步都需要從bufferpool中找到對應的頁,一旦沒有找到,也會發生磁碟載入到記憶體的情況。在葉子頁中,資料訪問操作符通過預期的鍵值搜尋頁中的行,並且複製所需的資料然後返回。不過也存在找不到符合鍵值的行。由於b-tree不僅可以定位行,還能找到大於鍵值的資料,所以b-tree可以雙向查詢,這個「大於」依賴於鍵的定義。這個跟索引定義中的公升序或降序不一樣,索引定義中的順序是b-tree的行的實際順序。
父操作符處理子操作符返回的結果。
父操作符繼續處理返回結果。
範圍掃瞄包含了範圍鍵值的尾部,再次呼叫next()方法時,如果行被移到高於範圍值尾部的地方。則會返回false。b-tree中的高於包含了公升序或排序。
對於rewind,b-tree同樣可以重綁。倒帶復位操作員狀態, 以使用相同的鍵/範圍引數重新啟動查詢/掃瞄。重新繫結將更改實際的鍵值。
擴充套件內容可見:showplan 邏輯運算子和物理運算子參考
從兩類操作可見,對於資料讀取,都是從快取中通過元資料的記錄去查詢資料,並且以遞迴迴圈的方式遍歷。
T SQL執行內幕(9) 資料訪問
在執行樹的葉子端 通常就是圖形化執行計畫每個分支的最右端 一般是實際訪問資料的操作符。當呼叫這些操作符上的next 方法時,會返回表或者索引上的實際資料。資料訪問通常有三類可能的操作符 各類掃瞄,掃瞄操作會在資料上迴圈訪問所有的行。它永遠不會定位乙個特定的行,取而代之的是掃瞄整個資料集。在執行計畫中...
cifar10資料的讀取
cifar10資料集檔案結構如圖所示,其中data batch 1 5.bin是訓練集,每個檔案包含10000個樣本,test batch.bin是測試集,包含10000個樣本。開啟任意乙個檔案,發現是一堆二進位制資料,其中乙個樣本由3037個位元組組成,其中第乙個位元組是label,剩餘3036 ...
CIFAR 10資料集讀取
參考 1 使用讀取方式pickle def unpickle file import pickle with open file,rb as fo dict pickle.load fo,encoding bytes return dict 返回的是乙個python字典 2 通過字典的內建函式,獲取...