常用執行計劃操作符
一、數據訪問操作符
1、SCAN操作符:掃描操作主要分為3種
Table Scan:當針對一個表(沒有聚集索引、堆表)執行一個查詢語句時,
此時將會做全表掃描操作(如果有where子句,則先執行全表掃描操作,然後在針對結果集做Filter操作)
示例:
Cluster Index Scan:聚集索引掃描,表中所有的數據都存在於聚集索引的葉節點中,因此聚集索引掃描相當於將整個表中的數據都取出。
Non-clustered Index Scan:當查詢的字段都被包含在一個覆蓋索引中的情況下,查詢優化器會優先使用Index Scan來查找這些數據,
因為非聚集索引比聚集索引占用的空間小,I/O成本更低。
示例:在Test表上創建一個覆蓋索引
Create index idx_Name_IdentityNo_Sex_Age_Job_LiveAddress on Test(Name) INCLUDE(Sex,IdentityNo,Age,LiveAddress,Job)
查詢SQL
SELECT Name,Sex,IdentityNo,Age,LiveAddress,Job FROM dbo.Test
執行計劃如下
2、SEEK操作符:
根據索引的不同可以分為:聚集索引查詢、非聚集索引查找
聚集索引查找發生在對聚集索引字段(一般情況下都是主鍵字段)進行where過濾的情況下
非聚集索引查找
3、Bookmark Lookup操作符:書簽查找發生在非聚集索引的語句中,用於查詢不包含在當前索引中的字段
一般優化手段是將額外的字段包含在一個Include索引中
二、連接操作符
1、Nested Loop
一般外表為小表(一般小於10000數據),較大數據表做為內表。循環嵌套連接查找內部循環表的次數等於外部循環的行數,
因此最好對內表的相應的字段上建索引,否則內表將需要做多次的全表掃描,性能有可能會產生影響。
2、Merge Join
一般而言,當輸入兩端有序的情況下,適用Merge Join效率會比較高。
示例:b表中的ProductID上有建索引,此時輸入兩端都處於有序狀態
SELECT b.SalesOrderDetailID,a.Name FROM Production.Product a JOIN Sales.SalesOrderDetail b ON a.ProductID=b.ProductID
如果輸入兩端處於無序的情況下,強制使用Merge Join連接,則將會額外多出排序操作以確保輸入兩端有序
SELECT b.SalesOrderDetailID,a.Name FROM Production.Product a INNER MERGE JOIN Sales.SalesOrderDetail b ON a.ListPrice=b.UnitPrice WHERE a.ListPrice>5
3、Hash Join
當連接表數據量較大,並且輸入兩端無序(連接列無索引)時,查詢優化器將優先使用Hash Join連接方式
SELECT b.SalesOrderDetailID,a.Name FROM Production.Product a INNER JOIN Sales.SalesOrderDetail b ON a.ListPrice=b.UnitPrice
三、聚合操作符
聚合操作分兩類:Stream Aggregate(流聚合)和Hash Aggregate(哈希聚合)
1、流聚合:
流聚合中又分兩種:一種是不包含GROUP BY子句的也稱為標量聚合,另外一種是包含GROUP BY子句聚合
標量聚合示例:
Group By聚合示例:
由執行計劃可以看出,針對Group By字段上建立合適的索引,將省去額外的Sort操作。
2、哈希聚合:
當數據量較大,且輸入端數據無排序的情況下,查詢優化器一般會使用哈希聚合(叠代器名稱為:Hash Match)
示例:
SELECT UnitPrice,COUNT(1) FROM Sales.SalesOrderDetail GROUP BY UnitPrice
常用執行計劃操作符