天天看點

執行查詢 第一篇:基本概念

SQL Server 是如何執行查詢腳本的呢?首先,應用程式連接配接到SQL Server引擎, 向SQL Server發送請求。一旦應用程式連接配接到資料庫引擎,SQL Server 建立會話(Session),用于表示用戶端和伺服器端之間資料交換的狀态。其次,SQL Server引擎配置設定Task來接受查詢請求,然後,SQL Server把Workder 綁定到Task,開始配置設定CPU資源和記憶體資源來處理Task。最後,通過解析、編譯和優化,進入查詢引擎,真正開始執行查詢請求。下圖從高層次上概括了SQL Server執行TSQL腳本的流程:

執行查詢 第一篇:基本概念

對于圖中的相關元件,先來了解一下其基本的概念和功能。

一,Connections

連接配接,這是在底層協定上實作的實際的實體連接配接,在用戶端向資料庫引擎發送請求之前,必須建立應用程式和資料庫引擎之間的實體連結,是應用程式和資料庫引擎之間聯系的實體通道,有三種連接配接的類型:TCP socket,命名管道(named pipe)和共享記憶體(shared memory)。相關的DMV:sys.dm_exec_connections。

二,Sessions

會話,當用戶端應用程式連到SQL Server時,兩端就會建立起一個“會話”用于交換資訊。嚴格來說,會話不是底層的實體連接配接,是SQL Server對連接配接的邏輯表示,用于存儲在資料庫引擎和應用程式之間連接配接時所需要的設定,比如,登陸資訊,事務的隔離級别,會話的SET選項等。但是,在實際應用中,通常可以把會話視為連接配接。

當發現一個session有多個值時,意味着出現了并行查詢。一個并行查詢使用相同的會話來連接配接用戶端,但是在SQL Server端使用多個Worker(Thread)用于服務這個請求。相關DMV:sys.dm_exec_sessions,當你看到有多行資料有相同的Session ID時,這是因為SQL Server 使用多個線程來處理一個查詢請求。

通常情況下,一個Connection對應一個Session,有時,可能存在多個Session對應一個Connection的情況,這是MARS(Multiple Active Result Sets)現象。

三,Request

請求,在SQL Server 的語境下,是查詢或批的邏輯表示。

SQL Server是一個 Client-Server平台,用戶端與伺服器(後端資料庫)互動的唯一方式是通過發送包含指令的請求到資料庫,而用戶端與伺服器端互動的協定簡稱為TDS(Tabular Data Stream)。應用程式使用SqlClient、OleDB、ODBC、JDBC等驅動來實作這種協定。當應用程式需要對資料庫執行任何操作時,它都通過TDS協定向資料庫引擎發送一個請求(request)。

簡單來說,每次對資料庫的操作都會以“請求”的形式發送給資料庫伺服器,發送請求有多種類型,主要是:Batch Request、RPC Request、Bulk Load Request。

  • Batch Request:批請求,此請求類型僅包含要執行的批處理的T-SQL文本。
  • RPC Request:遠端過程調用請求(Remote Procedure Call Request),用于執行存儲過程。
  • Bulk Load Request:大容量加載請求,用于執行大容量插入(Bulk Insert)操作

相關的DMV是:sys.dm_exec_requests。

四,Tasks

任務,在一個完整的TDS請求達到資料庫引擎時,SQL Server将會建立一個任務(Task)來處理請求。當Request到達SQL Server之後,後續操作都發生在SQL Server内部。使用者可以從  sys.dm_exec_requests 檢視資料庫引擎接收到的所有請求。一旦一個Task接收一個請求,Task的狀态由PENDING 轉變為可用。

當任務被建立用于處理請求時,該Task将代表請求從開始到完成的整過程。例如,如果請求是SQL Batch類型的請求,則任務将代表整個批次,而不是單個語句,SQL Batch中的單個語句不會建立新任務。批進行中的某些個别語句可以并行執行(通常稱為DOP,并行度),在這種情況下,任務将産生新的子任務以并行執行。如果請求傳回結果,則當用戶端完全使用結果時(例如,當您處置SqlDataReader時),批處理就完成了。您可以通過查詢sys.dm_os_tasks 來檢視伺服器中的任務清單。

當新的請求到達伺服器并建立任務以處理該請求時,處于PENDING狀态。在此階段,伺服器尚不知道請求實際上是什麼。該任務必須首先開始執行,為此,引擎必須為其配置設定一個工作程式(Worker)。

當一個新請求到達伺服器并且建立一個對應的任務時,首先會處于PENDING(挂起狀态),任務的狀态可以有:

  • PENDING:正在等待工作線程(Worker Thread)。
  • RUNNABLE:可運作,但正在等待接收一個時間片(quantum)。
  • RUNNING:目前正在Scheduler中運作。
  • SUSPENDED:擁有worker,但是正在等待某些事件(向RUNNABLE轉變)
  • DONE:已經完成。
  • SPINLOOP:陷入自旋鎖。

五,Workers

工作程序,Workers是SQL Server的線程池,伺服器在啟動時會建立一定數量的Worker(工作程式),并且可以按需建立更多工作程式,直到配置的最大工作程式線程(max worker threads)。隻有Worker才能執行代碼,Worker等待PENDING任務變為可用(當Task被配置設定用于處理請求),然後每個Workder被配置設定到一個Task,并執行該Task。Workder會一直執行(running),直到任務完全完成。

當沒有更多可用的Worker(工作程序)時,正在等待處理(PENDING)的任務将不得不等待,直到正在執行的(running)任務完成,或者執行該任務的Workder變得可用,能夠執行下一個PENDING的任務為止。

對于一個SQL批處理請求,承擔該任務的工作程序将執行整個SQL批處理(每個語句)。對于SQL批進行中的語句(=> request => task => worker)是否可以并行執行,答案是否定的,因為它們是在單個線程(=> worker)上執行的,是以每個語句必須按照順序來執行。

對于使用并行選項(DOP> 1)的語句,SQL Server會建立子任務,每個子任務都會經曆完全相同的周期:建立子任務(PENDING),工作程式必須拾取子任務并執行(與SQL批處理工作者不同的工作程式),通過查詢sys.dm_os_workers可以檢視SQL Server中工作程式的清單和狀态。

六,Scheduler

排程程式(Scheduler)是指SOS scheduler,用于管理Worker對CPU時間的需求,協調各個Worker對CPU資源的利用。每一個Scheduler都映射到一個單獨的CPU,Workder在一個排程程式中保持活躍/運作(Running)的時間稱作一個時間片(Quantum),最長時長為4毫秒。在其時間片到期之後,一個Worker主動退出,把時間片讓給其他需要通路CPU資源的Workder,并修改自身的狀态為RUNNABLE,這種排程方式稱為非搶占式排程。

參考文檔:

Thread and Task Architecture Guide

Understanding how SQL Server executes a query

Understanding how SQL Server executes a query

T-SQL執行内幕(1)——簡介