Sql-Server

執行計劃索引建議——相似查詢的區別

  • September 14, 2014

我正在嘗試分析此表上的查詢:

CREATE TABLE [dbo].[Values](
   [tid] [smallint] NOT NULL,
   [t] [datetime2](3) NOT NULL,
   [v] [real] NOT NULL,
CONSTRAINT [PK_Values_Unique] PRIMARY KEY CLUSTERED 
(
   [t] ASC,
   [tid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我正在使用SQL Server Management Studio審查一些**估計的執行計劃第一次查詢

SELECT *
FROM [dbo].[Values]
WHERE  [tid] = 1

顯示此查詢的估計執行計劃會產生:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Values] ([tid])
INCLUDE ([timestamp],[v])

我可以理解,它希望通過 快速查找tid,儘管我不完全為什麼INCLUDE建議這樣做。

然後我嘗試了第二個查詢(另一個 tid),這與另一個幾乎相同tid

SELECT *
FROM [dbo].[Values]
WHERE  [tid] = 1 or [tid] = 2

但是現在,SSMS不建議使用以前的索引。

為什麼SSMS為第一個查詢建議一個 INDEX,但現在不建議第二個查詢,儘管它們幾乎相同?

添加這個建議的 INDEX 是否對這兩種類型的查詢都有幫助?

**編輯:**這個表有超過 2 * 10^9 行。

一些上下文

首先要注意的是,聚集索引對查找列沒有幫助tid,因為t它是索引中的前導列。

如果您在鍵中翻轉和的順序ttid我希望索引提示消失並且查詢執行得更快而無需添加任何新索引。

具體答案

第二個查詢計劃不建議索引的最可能原因是新過濾器tid選擇了表中所有值的 30% 以上。在這種情況下,SQL Server 通常會更喜歡表掃描而不是查找索引(因為這是更好的策略)。因此,建議索引不再是正確的做法。選擇兩個值而不是一個值可能正是優化器中這個 30% 常數的臨界點

要探索這種效果,您可以通過執行以下操作強制返回索引提示:

SELECT *
FROM [dbo].[Values] WITH (FORCESEEK)
WHERE  [tid] = 1 or [tid] = 2

..但請不要在生產中這樣做,只是為了探索效果。

為什麼包含?

包含在那裡,因為如果不是,執行將不得不這樣做:

  1. 在新創建的索引中找到您要查找的值 tid
  2. 轉到主索引(主鍵)以獲取列的值vt

INCLUDE 確保所有列都包含在索引中,因此不需要第二步。順便說一句,這是您應該避免使用 SELECT * 的原因之一。

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