Sql-Server
執行計劃索引建議——相似查詢的區別
我正在嘗試分析此表上的查詢:
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
它是索引中的前導列。如果您在鍵中翻轉和的順序
t
,tid
我希望索引提示消失並且查詢執行得更快而無需添加任何新索引。具體答案
第二個查詢計劃不建議索引的最可能原因是新過濾器
tid
選擇了表中所有值的 30% 以上。在這種情況下,SQL Server 通常會更喜歡表掃描而不是查找索引(因為這是更好的策略)。因此,建議索引不再是正確的做法。選擇兩個值而不是一個值可能正是優化器中這個 30% 常數的臨界點要探索這種效果,您可以通過執行以下操作強制返回索引提示:
SELECT * FROM [dbo].[Values] WITH (FORCESEEK) WHERE [tid] = 1 or [tid] = 2
..但請不要在生產中這樣做,只是為了探索效果。
為什麼包含?
包含在那裡,因為如果不是,執行將不得不這樣做:
- 在新創建的索引中找到您要查找的值
tid
- 轉到主索引(主鍵)以獲取列的值
v
和t
INCLUDE 確保所有列都包含在索引中,因此不需要第二步。順便說一句,這是您應該避免使用 SELECT * 的原因之一。