T SQL執行內幕(9) 資料訪問

2021-08-17 21:56:25 字數 2007 閱讀 8720

在執行樹的葉子端(通常就是圖形化執行計畫每個分支的最右端),一般是實際訪問資料的操作符。當呼叫這些操作符上的next()方法時,會返回表或者索引上的實際資料。資料訪問通常有三類可能的操作符:

各類掃瞄,掃瞄操作會在資料上迴圈訪問所有的行。它永遠不會定位乙個特定的行,取而代之的是掃瞄整個資料集。在執行計畫中常見的掃瞄操作符有:聚集索引掃瞄(clustered_index_scan)、非聚集索引掃瞄(nonclustered_index_scan)、表掃瞄(table_scan)、遠端索引掃瞄(remote_index_scan)和遠端掃瞄(remote_scan)。由於應用在不同的資料來源(表、索引、遠端鏈結伺服器),所以這些掃瞄不是相同的操作符,但是都有相同的端對端掃瞄行為。同時由於需要讀取整個資料集,所以往往都是高開銷操作,理想情況下,僅適合資料倉儲查詢。

查詢操作,通過鍵直接定位一行資料,因此只能應用在b-tree結構的資料來源中,也就是聚集索引和非聚集索引上。如果乙個索引是復合索引(多列),那麼查詢操作僅對索引鍵的最左邊那列進行操作,比如乙個索引有且順序為abc三列,而語句中出現如where a=』a』 and b=』b』 and c=』c』或where a=』a』 and b=』b』或者where a=』a』這種都可以使用到該索引進行查詢操作,但是如果where只有b=』b』或者c=』c』等沒有a列出現,則索引不能進行查詢操作,通常就是使用掃瞄。注意從sql 2005開始where條件的列順序已經無關緊要。

另外,查詢操作也適用於範圍查詢,比如上面的索引,如果where a >』a』 and a<』z』是可以用到索引查詢,但是如果wherea=』a』 and b>』b』 and b<』z』這種,對b的範圍查詢並不會用到索引查詢,僅會對a=』a』進行查詢。

執行計畫中可能出現clustered_index_seek或者remote_index_seek這類操作符,他們同樣由於不同的資料來源所以是不同的操作型別,但是依舊可以通過鍵值來高效定位某個資料或者某個範圍值。

前面提到過,查詢操作僅能發生在b-treee結構上,所以不存在堆查詢。對於絕大部分oltp系統而言,應該廣泛使用這種方式查詢資料。

書籤查詢,一種特殊的資料訪問操作符,可以基於特定型別的值(稱為書籤)高效定位一行資料。但是僅能由資料庫引擎執行,使用者無法通過語句或者hints來進行強制。同時跟查詢和掃瞄不同的是它永遠不是主要的資料訪問操作符,只是用來查詢之前乙個查詢或掃瞄操作訪問過的資料。簡單來說就是協助查詢或掃瞄操作進行額外的資料獲取。書籤查詢可以應用在任何資料結構,包括堆和b-tree。分別稱為rid lookup(rid查詢)和key lookup(鍵值查詢)。注意從sql 2008開始,書籤查詢這個名字已經被rid 查詢和鍵值查詢所替代,書籤查詢僅作為這兩個查詢的統稱。

從效能優化方面來說,出現書籤查詢意味著你的非聚集索引無法覆蓋特定查詢所用到的列,對於大部分情況,可以通過修改現有非聚集索引來去除書籤查詢,畢竟它往往意味著引入了額外的i/o。不過也有一些情況,比如select *,非聚集索引往往不會也不應該覆蓋所有的列,所以這個時候,可能書籤查詢甚至聚集索引操作反而更高效。

嚴格來說,所有用於增、刪、改資料的操作符同樣都是資料訪問操作符。在觸發器中,inserted和deleted分別使用insertedscan和deleted scan操作符。log rowscan是乙個神秘的資料訪問操作符(從log中讀取資料而不是從資料表中讀取)。

在很多文獻、文章中還會看到範圍掃瞄(range scan),這意味著乙個查詢操作符快速定位乙個基於鍵值的行然後從當前位置繼續向前迴圈遍歷行,有時候止於特定的第二個鍵值。查詢操作基於開始和結束的鍵定義進行掃瞄,因此叫做範圍掃瞄。

回到執行計畫,當查詢樹根節點對操作符呼叫next()方法時,會逐級呼叫其子操作符直到到達資料訪問操作符為止。這些資料訪問操作符通過讀取第一條符合要求的實際資料並返回來實現next()方法。然後記錄位置之後,接下來再次呼叫next()方法讀取下一行並返回,直到全部讀取完畢。資料訪問操作符沒有更多的子操作符,它們就位於查詢樹的葉子端(圖形計畫的最右端)。在資料訪問操作符的上級通常是實現某些功能的操作符,如過濾(filter)、表關聯(join)、排序(sort)、聚合(computing aggregate)等。

簡單來說,對於各種操作符可以歸納以下行為:

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

關係型資料庫的資料訪問操作總是從記憶體的快取中讀取資料而不是從磁碟中讀取。這個快取稱為buffer pool。如果資料訪問操作符未能在快取中找到所需的資料,那麼就需要從磁碟中載入,這就會產生乙個磁碟i o讀 set statistics io on中的物理讀 並且需要等待這個物理讀完成 及從磁碟找到...

Swift 5將強制執行記憶體獨佔訪問

swift 5將帶來改進的swift程式記憶體安全性,在程式的其他部分修改變數時,不允許通過其他變數名來訪問這些變數。這個變更對現有應用程式的行為和swift編譯器本身都有重要影響。swift 5將帶來改進的swift程式記憶體安全性,在程式的其他部分修改變數時,不允許通過其他變數名來訪問這些變數。...

Swift 5將強制執行記憶體獨佔訪問

swift 5將帶來改進的swift程式記憶體安全性,在程式的其他部分修改變數時,不允許通過其他變數名來訪問這些變數。這個變更對現有應用程式的行為和swift編譯器本身都有重要影響。swift 5將帶來改進的swift程式記憶體安全性,在程式的其他部分修改變數時,不允許通過其他變數名來訪問這些變數。...