索引的訪問-SQL Server

分類:IT技術 時間:2016-10-09

全表掃描

無序掃描

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

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

表掃描

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

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

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


SQL Server將根據該表的IAM頁指示磁臂按物理順序掃描屬於該表的區,邏輯讀取數等於該表所包含的頁數。但是在這種掃描中,SQL Server通常使用非常高效的預讀策略(針對連續I/O),利用該策略可以在大於8 KB(頁)的大塊(區)中讀取數據,因此實際讀取數會小於該表所包含的頁數。

無序聚集索引掃描

在聚集表上進行無序全表掃描稱為無序聚集索引掃描。盡管表上有聚集索引,SQL Server仍然使用聚集索引(聚集表)的IAM頁來連續地掃描數據,這就意味著該訪問方法並不依賴於維護聚集索引邏輯順序的鏈接列表,而是按聚集索引葉級頁在磁盤上的物理順序進行。

因為該操作與表掃描沒有什麽不同,所以統稱表掃描


無序覆蓋非聚聚索引掃描

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

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

SELECT orderid FROM  Orders;

SQL Server使用非聚集索引的IAM頁來連續掃描非聚集索引的葉級頁,按照非聚集索引的葉級頁在磁盤中的物理順序進行訪問。


有序掃描

有序聚集索引掃描

有序聚集索引掃描是按鏈接列表對聚集索引葉級執行的完整掃描。

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

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

ORDER BY orderdate;


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

有序覆蓋非聚集索引掃描

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

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

SELECT orderid FROM Orders ORDER BY orderid;


局部掃描

有序掃描

非聚集索引查找+有序局部掃描+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;



在聚集表上應用

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

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

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





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

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

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

SELECT orderid, custid, empid, shipperid, orderdate

FROM Orders

WHERE orderdate = '20060212';

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

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


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

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

例如,表Orders在(custidorderdate)具有非聚集索引,並且該聚集索引覆蓋了如下查詢。

SELECT  orderdate, custid

FROM Orders

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

無序掃描

無序非聚集索引掃描+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';



在聚集表上的應用

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

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









Tags:

文章來源:


ads
ads

相關文章
ads

相關文章

ad