一句簡單的SQL查詢語句的背後...

weixin_33816946發表於2008-07-31

當我們在SQL Server Management Studio的查詢裡面輸入: SELECT * FROM t1 WHERE c1=2;

背後發生了什麼?資料庫怎麼去執行查詢的?知其然不知其所以然。

 

1.         Query Parsing, Synatax Error Check, and Authorization: Query Processer check the user is authorized to run the query;(查詢處理器首先進行語法解析,語法檢查,並檢查授權。如果沒有獲得授權執行相關的操作,或者語法錯誤,將報錯。)

2.         Query Re-writingSemantic Optimization (查詢處理器重新寫SQL語句並做相應的優化)。

例如:SELECT Emp.name, Emp.salary
                         FROM Emp, Dept
                            WHERE Emp.deptno = Dept.dno

              Join是多餘的,查詢處理器會重寫該語句並刪除到表DeptJoin

3.         Compile the SQL into internal query Plan; (編譯SQL到內部查詢計劃)

       資料庫會選擇最佳的方法來計算結果集。例如進行全表掃描,或是使用索引(pairs of key and location類似書的目錄)。資料庫會比較它們的成本,並形成內部執行計劃。資料庫內部負責計算選擇最佳執行計劃的元件叫優化器(Optimizer)。

4.         The query plan is handled by plan executor, which consists of many operators, e.g. joining, sorting, grouping... (查詢計劃被計劃執行器執行。計劃執行器包含很多操作者,例如執行Join, Sort, Group等,還要有訪問方法管理器來決定存取哪些資料頁或索引頁,或是直接快取命中,這些有緩衝管理器負責... ...)

5.         Transaction manager is started as well to ensure the ACID of operations. (事務管理器同時啟動來保證原子操作的併發一致性, 其他例如鎖管理器、索引管理器、行管理器、頁面檔案管理器、緩衝管理器、日誌管理器和等也會執行,而不是有查詢執行器一人包辦所有。)

 

執行如下語句:SELECT * FROM t1 WHERE c1=2的簡單過程:

 

1.        掃描t1表,如果是開始則取第一條記錄,否則取下一條記錄;如果讀到表的最後一條記錄了那麼跳到第4步。

2.        檢查記錄是否滿足WHERE條件;是則進入第3步,否則回到第1步。

3.        把記錄加到結果集。

4.        返回結果集給客戶端。

 

 

如果表有索引,優化器可能比較全表掃描和索引,並可能決定執行計劃為掃描索引。則步驟類似,不過第1步變成:

掃描索引(Clustered or no-clustered)並定位到記錄。

 

例如:

 SELECT * FROM Customers WHERE contactID IN

(SELECT contactID FROM Contacts WHERE contactID=86)

ORDER BY CustomerName DESC;

 

增加的步驟有:

1.        在表[Contacts]中掃描索引並定位記錄。

2.        在表[Customers]中掃描索引並定位記錄。

3.        Hash match (inner join),雜湊匹配,連線。

4.        Sort,排序

 

有關Join

SQL Server employs three types of join operations:

  • Nested loops joins
  • Merge joins
  • Hash joins

 

  1. 如果Join的輸入很小,例如小於10行,然後其他的Join輸入很大並且索引在其列上,則Nested loops joins是最快的。(原因參考Understanding Nested Loops Joins
  2. 如果兩個Join輸入都不小,但在索引列上排序(例如是在掃描排序的索引後獲得的 scanning sorted indexes),則Merge joins是最快的。(原因參考Understanding Merge Joins
  3. Hash joins可以有效的處理大量的、沒有排序的、沒有索引的輸入。尤其對複雜查詢的中間結果處理很有效。(更多參考Understanding Hash Joins

 

這些只是一些簡單的過程,其實資料庫內部執行過程是相當複雜的。雖然我們不是資料庫開發人員,但瞭解上下游的知識是必須的,能夠有助於我們的開發和應用。技術不僅要知道怎麼用,而且要知道為什麼,不能知其然不知其所以然。最後附上一張資料庫內部簡單結構圖供有興趣的人蔘考。

 

相關文章