Sql-Server

哪些索引用於在兩列上將表連接到自身

  • August 9, 2016

我正在使用 SQL Server 2016,並嘗試將表連接到自身,但查詢非常慢,這似乎是因為 SQL Server 拒絕使用索引。

如果你原諒這個例子的粗魯,我有一張這樣的桌子……

TABLE [Balances] (
   account_id NCHAR(20),
   balance_date DATE,
   balance INT,
   next_balance_date DATE
)

…我基本上想做這個查詢:

SELECT [t1].*, [t2].[balance] [next_balance]
FROM [Balances] [t1]
LEFT JOIN [Balances] [t2]
ON [t1].[next_balance_date] = [t2].[balance_date]
AND [t1].[account_id] = [t2].[account_id]

問題是,無論我嘗試在此表上放置什麼索引,SQL Server 都堅持進行雜湊匹配。在這個大型數據庫上這很慢。

我目前有以下索引:

NONCLUSTERED INDEX [idx_acc_date] ON [Balances]​ ([account_id] ASC, [balance_date] ASC)
NONCLUSTERED INDEX [idx_acc_nextdate] ON [Balances]​ ([account_id] ASC, [next_balance_date] ASC)​

我應該創建哪些索引來加速這個查詢?

(作為數據的一個小註釋 - 所有 balance_dates 都是在月底,因此 next_balance_date 也是如此。此外,每個 account_id 在每個 balance_date 只有一個條目。)

有 2 個選項:

  1. 通過 account_id 創建聚集索引。刪除所有其他索引。

  2. 添加新列Balance_ID INT IDENTITY(1,1)並在該列上創建聚集索引。僅在一個列上創建另一個非聚集索引account_id

第二種選擇更可取,因為它更快。您INT僅加入 4 個字節。雖然您目前的查詢加入了 40 個字節。這意味著您目前的運營成本要高出 10 倍。

另外,問自己幾個問題:

  • 你真的需要將 Account_ID 設為 Unicode 嗎?

  • 您可以將 Account_ID 轉換為 INT 或 BIGINT 嗎?

希望你明白我的意思。

添加:

  1. 您只在一列上創建聚集索引。從技術上講,您可以多次執行此操作,但主要目標是使其盡可能短。
  2. 如果您account_id在該列上創建了聚集索引,則不需要任何其他索引。
  3. 我可以猜測您的性能有所提高,因為在沒有聚集索引之前,索引非常糟糕,以至於 SQL 決定改為進行全表掃描。
  4. 建議:閱讀一本關於索引、它們的區別以及它們如何工作的書。

引用自:https://dba.stackexchange.com/questions/146129