Execution plan index suggestion - difference between similar queries I am trying to analyze queries on this table:

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]


I am reviewing some Estimated Execution Plans using SQL Server Management Studio, first query.

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


Displaying Estimated Execution Plan for this query yields:

CREATE NONCLUSTERED INDEX [&lt;Name of Missing Index, sysname,&gt;]
ON [dbo].[Values] ([tid])
INCLUDE ([timestamp],[v])


Which, I can understand, it wants to have a quick look up by tid, altough I don't fully why the INCLUDE is suggested.

Then I tried a second query (another tid), which is pretty the same with another tid:

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


But now, SSMS, doesn't suggest the previous index.

Why does SSMS suggests an INDEX for the first query but not for the second now although they are pretty the same ?

Should adding this suggested INDEX be helpful for both types of queries? 

EDIT: This table has over 2 * 10^9 rows.
Some context

The first things to observe is that your clustered index does not help with the lookup of the tid column, because t is the leading column in the index.

If you flipped the order of t and tid in the key, I would expect the index hint to go away and the query to run faster without adding any new indexes.

Specific Answer

The most likely reason that the second query plan does not suggest an index is that the new filter on tid picks more than around 30% of all the values in the table. When that is the case, SQL Server will generally prefer to table scan instead of seeking the index (because this is the better strategy). Hence, suggesting an index is no longer the right thing to do. Selecting two values instead of one may be exactly the tipping point of this 30% constant in the optimiser

To explore this effect, you can force the index hint to return by doing this:

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


.. But please don't do this in production, only to explore the effects.

Why the include?

The include is there because if it wasn't, the execution would have to do this:


Find the value you are looking for in the newly created index on
tid  
Go to the main index (the primary key) to pick up the values
of column v and t


The INCLUDE makes sure all the columns are contained in the index so the second step is not needed. Incidentally, this is one of the reasons why you should eschew SELECT *.