[MS SQL 筆記] 使用 SQL 索引中的 INCLUDE 關鍵字以提高查詢效能

Daniel Chang
4 min readFeb 17, 2023

當在 SQL Server 中創建 NonClustered Index時,可以使用 INCLUDE 子句來包含非索引欄位的資訊。在進行查詢時,如果查詢需要額外的欄位資訊,使用 INCLUDE 可以顯著提高查詢效能。

為了更好的理解這個概念,讓我們看一個例子。假設我們有一個 Customers 資料表,其中包含 LastName、FirstName、Email 和 Phone 等欄位。我們想要通過 LastName 查詢 Customers 資料表,並且需要 LastName、FirstName 和 Email 這三個欄位的資訊。可以使用以下的 SQL 查詢語句:

SELECT LastName, FirstName, Email 
FROM Customers
WHERE LastName = 'Smith'

如果在 Customers 資料表上沒有索引,則 SQL Server 將掃描整個表(Table Scan)以查找符合條件的資料。這種方式效率很低,特別是當表中資料量非常大的時候。為了提高效率,我們可以在 LastName 欄位上創建索引,使用以下的 SQL 語句:

CREATE NONCLUSTERED INDEX idx_nonclustered ON Customers(LastName)

創建索引之後,可以再次執行相同的 SQL 查詢語句。此時 SQL Server 會使用 idx_nonclustered 索引來查詢 Customers 資料表。由於索引僅包含 LastName 欄位的資訊,SQL Server 必須通過查詢的回溯操作(或二次查詢)來檢索 FirstName 和 Email 的值。回溯操作的流程如下:

  1. SQL Server 使用 idx_nonclustered 索引查詢符合條件的 LastName 資料行,並取得對應的 row ID。
  2. SQL Server 使用 row ID 查找 Customers 資料表中的該資料行。
  3. SQL Server 檢索 FirstName 和 Email 欄位的值。

由於需要回溯操作,這個查詢可能會比沒有索引的查詢還要慢。但是,如果使用 INCLUDE 子句來包含 FirstName 和 Email 欄位,SQL Server 就可以直接從索引中獲取這些欄位的值,而不需要進行回溯操作。使用 INCLUDE 可以顯著提高查詢效能。以下是帶有 INCLUDE 子句的 SQL 查詢語句:

CREATE NONCLUSTERED INDEX idx_nonclustered ON Customers(LastName) 
INCLUDE (FirstName, Email)

現在再次執行相同的 SQL 查詢語句。SQL Server 會使用 idx_nonclustered 索引來查詢 Customers 資料表,並使用這個索引來查詢 Customers 資料表,並且只會讀取 idx_nonclustered 索引頁面中的資料,而不必去讀取整個 Customers 資料表。

由於 idx_nonclustered 索引中包含了 FirstName 和 Email 欄位的資料,因此 SQL Server 可以直接從 idx_nonclustered 索引中讀取這些欄位的值,而不需要再做額外的查詢操作。這樣就可以大大提高查詢的效能。

簡單來說,INCLUDE 子句可以讓我們把非索引欄位的資料存儲到索引中,從而減少讀取整個資料列的操作,從而提高查詢效能。

需要注意的是,使用 INCLUDE 子句也可能會增加索引的大小,因此需要權衡索引大小和查詢效能之間的平衡。

INCLUDE子句在Clustered Index的指令中也能使用嗎?

INCLUDE 關鍵字同樣可以用在 CLUSTERED INDEX 的指令中。不過需要注意的是,對於 CLUSTERED INDEX,索引欄位的值本身已經包含整個資料列的資訊,因此使用 INCLUDE 子句時必須選擇非索引欄位,這樣才能進一步提高查詢效能。一般而言,將 INCLUDE 子句用於 CLUSTERED INDEX 的情況相對較少見,主要還是用於 NONCLUSTERED INDEX。

--

--