![](/img/trans.png)
[英]If I place a composite index on three columns and use them in the same query but in different places, will it still be effective?
[英]Composite index on three columns
我們得到了93M行的映射表,其中保存了三個表和對應的三個表的映射信息。 我們在從映射表訪問數據時面臨性能問題。
表名 | PK信息 | 行數 |
---|---|---|
賣方 | SellerId 主鍵 | 3000 行 |
店鋪 | StoreId 主鍵 | 20000 行 |
產品 | ProductId 主鍵 | 200k 行 |
賣家商店產品映射 | SellerId,ProductId,StoreId 復合非聚集索引。 此表中還有一個代理鍵:SellerStoreProductMappingId,用作集群的主鍵 | 93M 行 |
我們的查詢可以訪問以下三種組合中的任何一種:93M 行表中的Seller, Product, Store
。
我的實際查詢是這樣的:
SELECT < many columns from four tables>
FROM SellerStoreProductMapping
INNER JOIN Store
INNER JOIN Seller
INNER JOIN Product ...
WHERE SellerId = 123
但是,正在發生的是非聚集索引:SellerId、ProductId、StoreId 在我們的查詢中很少使用,即使我們對 SellerId 進行了過濾。 它用於 storeId 的索引掃描。
我們的疑問是,對於這三列組合,
注意:我們無法創建聚集列存儲索引,因為我們將 ROWVERSION 數據類型作為映射表中的數據類型之一。
這可能不是答案(但我不允許發表評論),還有一點需要考慮:綜合索引中的索引順序。
如果您在 SellerStoreProductMapping 表中按以下順序定義復合索引:SellerId,StoreId,ProductId,那么它只能有效地用於過濾 SellerID OR for (SellerId and StoreId) OR for (SellerId and StoreId and ProductId) 的查詢
如果您在查詢中將三列(7 種可能性)的所有可能組合作為過濾器,那么您可能需要定義至少三個單獨的索引。
可以在此處找到對此的一些參考: https://use-the-index-luke.com/sql/where-clause/the-equals-operator/concatenated-keys
如果該索引涵蓋了查詢中的所有信息並且謂詞是可搜索的,那么您的索引將被系統地使用。
例如,讓我們看看這些查詢:
--1
SELECT *
FROM SellerStoreProductMapping
WHERE Seller = 1 AND Product = 2 AND Store = 1
-- 2
SELECT Seller, Product, Store
FROM SellerStoreProductMapping
WHERE Seller = 1 AND Product = 2 AND Store = 1
-- 3
SELECT anyOtherColumns
FROM SellerStoreProductMapping
WHERE Seller = 1 AND Product = 2 AND Store = 1
-- 4
SELECT Seller, Product, Store
FROM SellerStoreProductMapping
WHERE Seller = 1 AND Product = 2 AND Store = 1
ORDER BY anyOtherColumns
只有查詢 2 會系統地使用索引。 所有其他查詢(1、3、4)沒有查詢中使用的所有列,在索引鍵中......所以他們必須使用雙重讀取:
兩次讀取的成本與掃描表等其他策略的成本相比。 如果掃描成本較低,則不會使用索引...
關於索引中的列順序要記住的一些經驗法則:
WHERE =
predicate 中引用的任何列以及唯一連接中引用的任何列放在索引鍵的第一個位置(連接從另一個表返回單行)> <= < <> BETWEEN
INCLUDE
因此,如果您的查詢是針對單個賣家和商店,但有很多產品,那么您需要一個索引(Seller, Store, Product)
或(Store, Seller, Product)
,具體取決於列的選擇性。
進一步說明:
如果您選擇的列未包含在索引中,編譯器可能會決定執行聚集索引掃描,因為額外的鍵查找成本可能不值得。
只有當編譯器可以計算出連接在唯一的行上時,編譯器才能檢測到唯一的連接表。 因此,請始終確保使用PRIMARY/UNIQUE KEY
或使用唯一索引聲明唯一列。
在您的情況下,您的連接表有一個額外的代理主鍵,我認為這是不必要的,因為其他三個列唯一地定義了該行。 即使你需要它,你也不必聚集在它上面。 您可以使用與 PK 完全分開的聚集索引(它充當包含所有列的索引)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.