實例:根據電話或電子郵件查詢會員
假設我們有一個大型的 MemberOrders 表,記錄會員的訂單資料,欄位包含:
PhoneEmailOrderStatusCreatedAtMemberId
現在有一個功能:使用者輸入電話或電子郵件其中之一,系統需要查詢「已完成」的訂單,並找出對應的會員 ID。
因此後端常會送出這個查詢:
SELECT
MemberId
FROM MemberOrders
WHERE OrderStatus = 'Completed' AND Phone = '0912345678'又或是以 email 查詢:
SELECT
MemberId
FROM MemberOrders
WHERE OrderStatus = 'Completed' AND Email = 'test@gmail.com'查詢特性是:
- 條件為 Phone 或 Email 二擇一
- 需要篩選 OrderStatus
- 最終只回傳 MemberId
如果資料表沒有索引,資料庫必須掃描整張表。
若只建立一個 (Phone, Email) 的複合索引,當查詢使用 Email 時,索引順序並不符合查詢條件,資料庫可能仍需掃描大量資料。
較佳做法是建立兩個非叢集索引:
CREATE NONCLUSTERED INDEX IX_MemberOrders_Phone_Status_CreatedAt
ON dbo.MemberOrders (Phone, OrderStatus)
INCLUDE (MemberId);
CREATE NONCLUSTERED INDEX IX_MemberOrders_Email_Status_CreatedAt
ON dbo.MemberOrders (Email, OrderStatus)
INCLUDE (MemberId);這樣,當查詢使用 Phone 時,資料庫可以透過第一個索引進行 Index Seek;當使用 Email 時,則使用第二個索引。由於索引包含 MemberId,查詢可以在索引內完成,不需要 Key Lookup。
這種設計讓查詢計畫穩定、可預期,且在資料量持續成長時仍能維持良好效能。