Sql-Server

強制 Sql 伺服器在合併連接中使用索引查找

  • May 7, 2020

我正在測試 sql server 中的 Merge join。我有一個INNER JOIN並強制優化器做MERGE JOIN

  • ID在個人表中是主鍵
  • ID在 Abteilung 表中是主鍵
  • 這些表中沒有其他索引
select * from  [dbo].[Personal] as P inner join [dbo].[Abteilung] as A  
on  P.[ID]= A.[Personal_ID]   OPTION (MERGE JOIN) 

然後優化器使用這個計劃來執行我的查詢:

在此處輸入圖像描述

我想強制優化器使用index seek而不是Table Scan

我為實現這一目標所做的工作:

  • 在表 Abteilung 中定義分組索引的列IDPersonal_ID。如果我執行查詢,執行計劃是這樣的變化:

在此處輸入圖像描述

這裡我有聚集索引掃描,但沒有聚集索引搜尋

  • 使用FORCESEEK提示。如果我使用此提示,則執行查詢會發生錯誤:

由於此查詢中定義的提示,查詢處理器無法生成查詢計劃。在不指定任何提示且不使用 SET FORCEPLAN 的情況下重新送出查詢。

  • 如果我在查詢中添加 where 子句,則查詢將更改為:
 select * from  [dbo].[Personal] as P inner join [dbo].[Abteilung] as A  
 on P.[ID]= A.[Personal_ID] where A.[Personal_ID]=2 
 OPTION (MERGE    JOIN)

在此處輸入圖像描述 在這種情況下,我只有聚集索引掃描。

我的問題:

如何更改我的查詢以使聚集索引搜尋在底線?

要獲得聚集索引搜尋,您需要一個支持過濾器的聚集索引(例如,前導鍵必須是Personal_ID,而不是ID)。

Personal_ID如果沒有支持過濾器的前導列的索引,則不能強制搜尋。

這並不意味著您應該更改現有的聚集索引,除非這是您曾經對該表執行的唯一查詢。

雖然您可以創建一個以作為鍵列的非聚集索引,Personal_ID但對該索引的查找可能不是您想要的 - 因為您正在使用SELECT * (您真的確定需要兩個表中的所有列嗎?),它無論如何都需要從聚集索引中獲取其餘列,如果返回的行數超過一定數量,則在某個時候進行搜尋(好吧,相當於偽裝成搜尋的範圍掃描)+查找將比正常掃描更昂貴。

為什麼你認為你需要在這裡尋找?查詢返回多少行,它們有多寬,需要多長時間?這只是教育性的,還是您假設搜尋總是比掃描更好?(它不會,順便說一句。)

一些有用的閱讀:

在沒有創建任何測試的情況下,我猜想在沒有搜尋謂詞的情況下搜尋索引是不可能的,特別是如果您使用 SELECT * 並獲取所有表列。

我會嘗試過濾作為您要查找的索引的一部分的索引列,並僅檢索該索引所涵蓋的列。

文件解釋說,合併連接通常會在之後對其進行掃描或排序。閱讀:https ://technet.microsoft.com/en-us/library/ms190967(v=sql.105).aspx

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