天天看點

索引的通路-SQL Server全表掃描局部掃描

目錄

全表掃描

無序掃描

表掃描/無序聚集索引掃描

無序覆寫非聚集索引掃描

有序掃描

有序聚集索引掃描

有序覆寫非聚集索引掃描

局部掃描

有序掃描

非聚集索引查找+有序局部掃描+lookups

聚集索引查找+有序局部掃描

覆寫非聚集索引查找+有序局部掃描

無序掃描

無序非聚集索引掃描+lookups

全表掃描

無序掃描

表掃描/無序聚集索引掃描

表掃描或無序聚集索引掃描都連續地掃描表中的所有資料頁。

表掃描

在堆上進行無序全表掃描稱為表掃描。

例如,Order表按堆結構組織(沒有聚集索引),執行如下查詢:

SELECT orderid, custid, empid, shipperid, orderdate FROM  Orders;

索引的通路-SQL Server全表掃描局部掃描

SQL Server将根據該表的IAM頁訓示磁臂按實體順序掃描屬于該表的區,邏輯讀取數等于該表所包含的頁數。但是在這種掃描中,SQL Server通常使用非常高效的預讀政策(針對連續I/O),利用該政策可以在大于8 KB(頁)的大塊(區)中讀取資料,是以實際讀取數會小于該表所包含的頁數。磁盤讀取的時間主要在磁臂的移動,讀取一個頁與讀取一個區的差別不大。

無序聚集索引掃描

在聚集表上進行無序全表掃描稱為無序聚集索引掃描。盡管表上有聚集索引,SQL Server仍然使用聚集索引(聚集表)的IAM頁來連續地掃描資料,這就意味着該通路方法并不依賴于維護聚集索引邏輯順序的連結清單,而是按聚集索引葉級頁在磁盤上的實體順序進行。

因為該操作與表掃描沒有什麼不同,是以統稱表掃描。

索引的通路-SQL Server全表掃描局部掃描

無序覆寫非聚集索引掃描

無序覆寫非聚集索引掃描概念類似于無序聚集索引掃描。覆寫索引表示非聚集索引(索引列)包含查詢中的所有列。換句話所,覆寫索引不是一個具有特殊屬性的索引,而是關于特定查詢的覆寫索引。SQL Server隻通路索引資料(非聚集索引葉級頁)就可以找到滿足查詢所需要的全部資料,而不用通路完整的資料行。另一方面,該通路方法與無序聚集索引掃描相同,隻不過覆寫非聚集索引的葉級比聚集索引的葉級包含的頁要少,是以行的大小更小(隻包含索引列),每個頁可以容納更多的行。

例如,Order表在orderid列上具有非聚集索引,這就意味着該表的所有orderid (訂單ID)都位于非聚集索引的葉級上,也就是說非聚集索引覆寫了上面的查詢。執行如下查詢:

SELECT orderid FROM  Orders;

SQL Server使用非聚集索引的IAM頁來連續掃描非聚集索引的葉級頁,按照非聚集索引的葉級頁在磁盤中的實體順序進行通路。

索引的通路-SQL Server全表掃描局部掃描

有序掃描

有序聚集索引掃描

有序聚集索引掃描是按連結清單對聚集索引葉級執行的完整掃描。

例如,Order表在orderdate列上具有聚集索引,執行如下查詢:

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

ORDER BY orderdate;

索引的通路-SQL Server全表掃描局部掃描

不同于無序索引掃描,有序掃描的性能取決于索引的碎片級别。也就是說,索引葉級别中無序頁占總頁數的百分比。無序頁是指,根據連結表邏輯上出現在一頁後面,但實體上卻在其前面的。對于沒有碎片的索引,有序索引掃描的性能接近于無序掃描,因為兩者都是連續地讀取實體上的資料。然而,随着碎片級别越來越高,他們性能差異就越來越顯著。當然,無序掃描性能更高。

有序覆寫非聚集索引掃描

有序覆寫非聚集索引掃描概念上類似于有序聚集索引掃描,隻不過前者隻需要通路非聚集索引葉級頁。因為隻涉及更少的頁,它的成本肯定比聚集索引掃描低。

例如,Order表在orderid列上具有非聚集索引,并且非聚集索引覆寫了我們的查詢,執行如下查詢:

SELECT orderid FROM Orders ORDER BY orderid;

索引的通路-SQL Server全表掃描局部掃描

局部掃描

有序掃描

非聚集索引查找+有序局部掃描+lookups

這種通路方式通常用于小範圍查詢(包括點查詢),且用到的非聚集索引沒有覆寫該查詢。

第一步,在非聚集索引内執行查找以定位被查詢範圍的第一個鍵(orderid=101)。

第二步,從該範圍内的第一個鍵開始在葉級别執行有序局部掃描,直到找到最後一個鍵。

第三步,為找的每個鍵查找(lookup)對應的資料行。

注意第三步不需要等到第二步執行完。對于該範圍内找到的每個鍵都應用lookup,在堆中執行lookup隻需讀取一頁,而聚集表中執行lookup所讀取的頁數等于聚集索引的級數。

這種通路方法中,第三步lookup操作通常會占查詢成本的一大部分,因為它涉及大量的I/O,了解這一點對評估性能很重要。Lookup為每個找到的鍵在堆中讀取一頁或在聚集索引中執行完整的查找(seek),而且lookup總是随機的I/O(不是連續I/O)。

要估算這種查詢的I/O成本,你通常可以重點關注lookups的成本,如果你想要更精确的估計I/O成本,還可以考慮對非聚集索引的查找和有序局部掃描。不過随着範圍越來越大,這部分的成本可以忽略不計。一次非聚集索引的查找操作的成本大約是3(非聚集索引的級數)次邏輯讀取。有序局部掃描的I/O成本取決于該範圍内的行數和非聚集索引葉級頁可容納的行數。一般局部掃描實際上并不包含額外的讀取,因為我們查找範圍内的所有鍵一般都位于查找操作所到達的葉級頁,或者在連結清單随後的一頁或多頁。Lookups操作的I/O成本等于該範圍内的行數乘以一次lookup的成本。對于堆上的lookup,成本為一次邏輯讀取。對于聚集表上的lookup,邏輯讀取數為聚集索引的級數。由于在聚集表中的所有的lookup操作都會查詢聚集索引的非葉級,聚集索引的非葉級通常位于緩存,是以你不用過于擔心在聚集表中進行lookup表面上的高成本。

在堆上應用

例如,Orders表(按堆組織)在orderid列上具有非聚集索引,但是該索引沒有覆寫如下查詢。

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE  orderid BETWEEN 101 AND 120;

索引的通路-SQL Server全表掃描局部掃描

在聚集表上應用

例如,Orders表在orderid列上具有聚集索引,在orderdate列上具有非聚集索引,表中沒有覆寫該查詢的索引。

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE  orderdate >= '20060101' AND orderdate < '20070101';

索引的通路-SQL Server全表掃描局部掃描

聚集索引查找+有序局部掃描

對于按聚集索引的第一個鍵列進行篩選的範圍查詢,采用這種通路方法。這種方法先執行查找操作(seek)找到該範圍内的第一個鍵,然後在聚集索引葉級應用局部掃描,從第一個鍵掃描到最後一個鍵。這種方法主要好處是它不涉及lookups。對于較大的範圍,lookups的成本非常高,随着範圍的越來越大,不涉及lookups的通路方法和使用非聚集索引及lookups的通路方法在性能方面差異會越來越大。

例如,表Orders在(orderdate,orderid)上具有聚集索引。執行如下查詢:

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE orderdate = '20060212';

雖然篩選器使用了等于運算符,但它本質上還是一個範圍查找,因為表中存在多個符合條件的行,點查詢也可以被看作是範圍查詢的一個特例。這種通路方法的成本包括在聚集索引上的查找成本(聚集索引級數)和聚集索引葉級頁内有序局部掃描的成本。

有序掃描通常占查詢成本的大部分,因為它涉及大部分的I/O。對于有序索引掃描,索引碎片具有至關重要的作用。當碎片處于最低級别,實體讀取幾乎是連續的。不過随着碎片級别不斷增大,磁臂必須瘋狂地來回移動,進而嚴重降低掃描的性能。

索引的通路-SQL Server全表掃描局部掃描

覆寫非聚集索引查找+有序局部掃描

覆寫非聚集索引查找+有序局部掃描這種通路方法幾乎與上一個通路方法相同,唯一的差別是前者使用覆寫非聚集索引,而不是聚集索引。要使用這種方法,被篩選列必須是索引的第一個鍵列。相對于上一個方法,這個通路方法的好處是在于非聚集索引的一個葉級頁可以比聚集索引的一個頁級頁容納更多的行,是以該通路方法的大部分成本,即葉級的局部掃描成本顯得更低,即在相同範圍内,被掃描的頁更少,當然索引碎片也對性能有重要的影響,因為局部掃描是有序的。

例如,表Orders在(custid,orderdate)具有非聚集索引,并且該聚集索引覆寫了如下查詢。

SELECT  orderdate, custid

FROM Orders

WHERE custid= 'C0000000001' AND orderdate >= '20060101' AND orderdate < '20070101';

索引的通路-SQL Server全表掃描局部掃描

無序掃描

無序非聚集索引掃描+lookups

适用條件:

1、該查詢的選擇性足夠高。選擇性被定義為查詢傳回的行占表中總行數的百分比。

2、非聚集索引沒有按順序維護被查找的鍵。例如,當你篩選的列不是非聚集索引的第一個鍵列時就屬于這種情況。

該通路方法将對索引葉級執行無序的完全掃描,然後再執行一系列的lookups。查詢的選擇性必須足夠高才能适用這種通路方法,否則,太多的lookup會使得該方法通路成本比直接掃描整個表還高。要計算查詢的選擇性,SQL Server需要有被篩選列的統計資訊(包含值分布的直方圖)。

該查詢的成本包括對非聚集索引的無序掃描(使用IAM頁的連續I/O)成本和lookups成本(随機I/O)。掃描非聚集索引的頁數等于非聚集索引葉級的頁數。lookups的成本等于符合條件的行數乘以一次lookup的成本。在堆上lookup成本為1次頁讀取,在聚集表上,邏輯讀取數為聚集索引的級數。

在堆上的應用

例如,表Order上具有非聚集索引(orderdate ,custid),其中custid不是非聚集索引中的第一個鍵列。執行如下查詢:

SELECT orderid, custid, empid, shipperid, orderdate  FROM Orders WHERE custid = 'C0000000001';

索引的通路-SQL Server全表掃描局部掃描

在聚集表上的應用

例如,表Order上具有非聚集索引(orderdate ,custid),其中custid不是非聚集索引中的第一個鍵列,此外表Order在列orderid上有聚集索引。執行如下查詢:

SELECT orderid, custid, empid, shipperid, orderdate  FROM Orders WHERE custid = 'C0000000001';

索引的通路-SQL Server全表掃描局部掃描

繼續閱讀