查詢最佳化工具核心剖析第七篇:執行引擎之資料訪問操作---Scan
從本篇了開始的接下來的幾篇文章將會介紹與執行引擎相關的知識。
系列文章索引:
查詢最佳化工具核心剖析第一篇 查詢最佳化工具核心剖析第二篇:產生候選執行計畫&執行計畫成本估算查詢最佳化工具核心剖析第三篇:查詢的執行與計劃的緩衝 & Hint提示 查詢最佳化工具核心剖析第四篇:從一個執行個體看執行計畫
查詢最佳化工具核心剖析第五篇:進一步的瞭解執行計畫
查詢最佳化工具核心剖析第七篇:執行引擎之資料訪問操作---Scan查詢最佳化工具核心剖析第八篇:執行引擎之資料訪問操作---Seek(上)
執行引擎就是由大量的物理操作組成的(而這些物理操作又會去調用儲存引起的相關方法),這些操作被查詢處理器用來高效的執行我們的查詢。
這裡不要將查詢處理器與查詢最佳化工具搞混淆,它們不是同一個東西。為了使得大家對相關的概念有一個清楚的認識,請看到下面這一個圖:
,就可以一目瞭然的直到查詢處理器與查詢最佳化工具之間的關係:
- 資料庫基本上有兩大部分組成:關聯式引擎,儲存引擎。(建議朋友們去仔細的閱讀這幾篇文章:SQL 內部機制之:一個查詢的生命週期)
- 我們這裡所說的“查詢處理器”就是圖中的關聯式引擎,而查詢最佳化工具只是其中的一個部分。
我們最近將要介紹的“執行引擎”,就是中的“Query Executor”。在介紹執行引擎的過程中,我這裡主要會著重的介紹幾類在我們查詢中常見的一些操作:資料訪問,彙總,Join,還有並行操作。當然,在執行引擎中,還有更多的操作,如果大家感興趣,可以去參看SQL Server的聯機叢書。
我們首先將會介紹給資料訪問的幾個操作:scan,seek,還有lookup。
相信大家對這些操作應該有所瞭解的,我這裡稍微的提及一下。
Scan:這個操作會讀取整個資料結構,這個資料結構可以是一個堆表,叢集索引,非叢集索引。
Seek:這個操作不會讀取整個資料結構,而是直接通過索引定位到要讀取的那一行。所以Seek操作只能發生在叢集索引與非叢集索引上。
堆表:就是沒有建立叢集索引的表,表中的資料沒有按照順序進行儲存。一旦一個表建立了叢集索引,那麼表中的資料就會按照叢集索引排序儲存。
另外,非叢集索引可以建立在堆表上,也可以建立在還有叢集索引的表上。
我們通過下面的一個表做一下總結(看看不同的資料結構可以支援何種物理操作),然後迅速進入Scan操作的詳細講解。
|
資料結構 |
Scan |
Seek |
|
堆表 |
Table Scan |
|
|
叢集索引 |
Clustered Index Scan |
Clustered Index Seek |
|
非叢集索引 |
Index Scan |
Index Seek |
還是和之前一樣,我們從一個例子入手,這裡依然使用樣本資料庫AdventureWorks。我們首先來看到一個Table Scan的操作(也就是整表掃描) ,看到如下的查詢:
查看實際的執行計畫,如:
通過查看DatabaseLog表的定義,我們發現這個表是一個堆表,即,這個表沒有叢集索引,如下所示:
下面,我們再看一個Clustered Index Scan(叢集索引掃描)的例子,看到如下查詢:
執行計畫如下如所示:
通過查看Address表的定義,發現這個表確實還有叢集索引:
可以上面的例子可以知道:
- 雖然同是進行了 Scan操作,但是因為表的一些特性不同,而最後選擇的具體的物理操作Scan也不一樣。
- 不管是Table Scan還是Clustered Index Scan,它們都是對相應的資料結構進行了全部的掃描,不同的是:前者發生在堆表上,後者發生在含有叢集索引的表上。
下面,給大家看一個比較有意思的查詢:
執行計畫如下:
圖中顯示的是Index Scan,也就說,這個查詢沒有去掃描表的所有資料頁,而是去掃描索引,這個成本小得多。之所以進行了這個操作,是因為在這個表上存在一個非叢集索引,定義如下:
這個非叢集索引包含了我們查詢中的兩個欄位:[City],[StateProvinceID]。又因為AddressID是這個表的叢集索引,對於一個有叢集索引的表而言,它的所有的非叢集索引都會包含一個對叢集索引的引用,這樣是為了加快資料檢索的速度(大家可以想想為什嗎?)。所以,我們上面查詢中的三個操作都可以在索引頁中找到,就沒有必要去掃描底層的表了。