查詢處理是DBMS的核心,而查詢優化又是查詢處理中的關鍵技術。
本章介紹關系數據庫的查詢處理(query processing)和查詢優化(query optimization)技術,查詢優化技術一般可分為代數優化和物理優化。代數優化指關系代數表達式的優化;物理優化指通過存取路徑和底層操作算法的選擇進行優化。
一、查詢處理
查詢處理步驟
關系數據庫查詢處理可以分為4個階段:查詢分析、查詢檢查、查詢優化和查詢執行,如下圖所示:

1. 查詢分析
對查詢語句進行掃描、詞法分析和語法分析。判斷是否符合SQL語法規則,若沒有語法錯誤就轉入下一步處理,否則便報告語句中出現的語法錯誤。
2. 查詢檢查
對合法的查詢語句進行語義檢查。根據數據字典中關系模式的定義檢查語句中的數據對象,如關系名、屬性名是否存在和有效;還要根據數據字典中用戶權限和完整性約束的定義對用戶的存取權限進行檢查。若通過檢查便將SQL語句轉換成內部表示,即等價的關系代數表達式。RDBMS一般使用查詢樹(query tree)或者語法分析樹(syntax tree)來表示擴展的關系代數表達式。
3. 查詢優化
每個查詢都會有許多可供選擇的執行策略和操作算法,查詢優化就是選擇一個高效執行的查詢處理策略。一般將查詢優化分為代數優化和物理優化。代數優化指對關系代數表達式進行等價變換,改變代數表達式中操作的次序和組合,使查詢執行更高效;物理優化則指存取路徑和底層操作算法的選擇。選擇依據可以是基於規則、代價、語義的。
4. 查詢執行
依據優化器得到的執行策略生成執行查詢計划,由代碼生成器(code generator)生成執行這個查詢計划的代碼,然后執行並送回查詢結果。
實現查詢操作的算法示例
1. 單表選擇操作
例1:SELECT * FROM Student WHERE <條件表達式>
考慮<條件表達式>的可能情況:
- C1:無條件
- C2:Sno = '20121212'
- C3:sage >= 20
- C4:Sdept = 'CS' AND Sage > 20
對於單表選擇,一般采用全表掃描或基於索引的算法:
(1) 全表掃描
按物理次序讀取Student的存儲塊到內存,檢查每個元組\(t\),如果\(t\)滿足選擇條件,則輸出\(t\)。
(2) 索引掃描算法
-
對於C2,若Sno上有索引,則可使用索引找到符合條件的元組的指針,再通過指針檢索到相應元組。
-
對於C3,若Sage上有B+樹索引,則可使用B+樹索引找到
Sage=20的索引項,以此為入口點,在B+樹的順序集上得到Sage>20的所有元組指針,再通過指針檢索相應的元組。 -
對於C4,若Sdept和Sage上都有索引,有兩種實施方法:①先分別找出符合兩條件的元組,然后求交集;②先找出符合其中條件一的元組集,然后再在該集合中找出符合條件二的元組,以此類推。
2. 連接查詢操作
(1) 嵌套循環算法
最簡單可行。對外層循環的每一個元組,檢索內層循環中的每一個元組,並檢查這兩個元組在連接屬性上是否相等。如果滿足條件,則串接后作為結果輸出。
(2) 排序-合並算法
等值連接最常用的算法,尤其適合參與連接的諸表已經排好序的情況。① 對參與連接的表,首先對這些表按連接屬性排序;② 對表一中每個元素,依次掃描表二中具有相同連接屬性的元組,將他們連接;③ 當掃描到第一個不相同的元組時,返回並選擇表一的下一個元素,繼續執行上述操作;

(3) 索引連接(index join)算法
索引連接算法的步驟是:① 在表一上建立連接屬性索引;② 對表二中的每個元組,由Sno值通過SC的索引查找相應的SC元組;③ 把這些表一元組和表二元組連接起來;
(4) 哈希連接(hash join)算法
hash join算法也是處理等值連接的算法。它將連接函數作為hash碼,用同一個hash函數把表一和表二的元組散列到hash表中。① 划分階段,也稱創建階段,即創建hash表。對包含較少元組的表進行一遍處理,把它的元組按hash函數分散到hash表的桶中;② 試探階段,也稱連接階段,對另一個表進行一遍處理,把該表的元組也按同一個哈希函數進行散列,找到合適的hash桶,並把該元組與桶中來自表一的元組連接起來。
二 、關系數據庫的查詢優化
關系查詢優化是影響關系數據庫管理系統性能的關鍵因素。
優化對關系系統來說既是挑戰又是機遇。挑戰在於為了達到用戶可接受的性能必須進行查詢優化;而機遇在於關系數據庫可以從關系表達式中分析查詢語義,存在着查詢優化的可能,這也是關系系統在性能上能夠接近甚至超過非關系系統的原因。
查詢優化概述
在非關系系統中,用戶需要使用過程化語言表達查詢請求,因此用戶必須了解存取路徑,系統則需要提供用戶選擇存取路徑的手段,查詢效率由用戶的存取策略決定。而在關系系統中,用戶只需提出"干什么”,而不必指出“怎么干”,查詢優化交由系統來做,而系統通常比用戶程序的“優化”做得更好,這是因為:
- 優化器可以從數據字典中獲取許多統計信息,如每個關系表中元組數、關系中每個屬性值的分布情況等;
- 優化器可以考慮數百種不同的執行計划,而普通的程序員則一般只能考慮有限的幾種;
- 優化器中包含了很多復雜的優化技術,而這些優化技術往往只有最好的程序員才能掌握。而系統的自動優化使得所有人都擁有這些優化技術。
在集中式數據庫中,查詢執行開銷主要包括磁盤存取塊數(IO代價)、處理機時間(CPU代價)、查詢的內存開銷。
三、代數優化
關系代數表達式等價變換規則
代數優化是用過對關系表達式進行等價變換來提高查詢效率。
兩個關系表達式\(E_1\)和\(E_2\)是等價的,可記為\(E_1\equiv E_2\)。
常見變換規則見《數據庫系統概論》王珊第五版 P283。
查詢樹的啟發式優化
- 選擇運算應盡可能先做,投影次之。因為選擇操作通常使計算的大大變小,投影操作去除不必要的字段。
- 把投影和選擇運算同時進行。
- 把某些選擇同在它前面要執行的笛卡爾積結合起來成為一個連接運算。
- 找出公共子表達式。
四、物理優化
物理優化即選擇高效合理的操作算法或存取路徑,求得優化的查詢計划,達到查詢優化的目標。
方法常有:
- 基於規則的啟發式優化
- 基於代價估計的優化
- 兩者結合的優化方法
基於啟發式規則的存取路徑選擇優化
1. 選擇操作的啟發式規則
對於小關系,使用全表掃描,即使選擇列上有索引。
對於大關系,啟發式規則有:
- 對於選擇條件是“主鍵 = 值”的查詢,查詢結果最多只是一個元組,可使用主碼索引;
- 對於選擇條件使“非主屬性 = 值”的查詢,並且選擇列上有索引,則要估計查詢結果的元組數目,若比例較小(<10%)可使用索引掃描,否則還是全表順序掃描;
- 對於選擇條件是屬性上的非等值查詢或范圍查詢,並且選擇列上有索引,同樣要估計查詢結果的元組數目,如果比例較小(<10%)可使用索引掃描方法,否則還是使用全表順序掃描;
- 對於用AND連接的選擇條件,如果有涉及這些屬性的組合索引,則優先采用組合索引掃描;若某些屬性上有一般索引,可使用索引掃描方法,否則使用全表順序掃描;
- 對於用OR連接的選擇條件,一般使用全表順序掃描。
2. 連接操作的啟發式規則
- 如果兩個表已按連接屬性排序,則選用排序-合並算法;
- 如果一個表在連接屬性上有索引,則可以選用索引連接算法;
- 如果上面兩個規則都不適用,其中一個表較小,則可使用hash join算法;
- 最后可選擇嵌套循環算法,選擇其中較小的表作為外層循環。
基於代價的優化方法
基於代價的優化方法要計算各種操作算法的執行代價,它與數據庫的狀態緊密相關
統計信息
在數據字典存儲了優化器所需要的統計信息(database statistics),主要包括以下方面:
- 對每個基本表,該表的元組總數、元組長度、占用的塊數、占用的溢出塊數;
- 對每個基本表的每個列,該列的不同值的個數、該列的最大值、最小值,該列上是否已建立了索引,是那種索引(B+樹索引、hash索引、聚集索引)。
- 索引的一些信息,如果B+樹索引,該索引的層數、不同索引值的個數、索引的葉節點數。
優化器根據數據字典中的統計信息來進行策略選擇。
