sql-server add tag
meme (imported from SE)
I have a SQL Server database where the queries are pretty slow, and there's a lot of locking and blocking. 

When I look at the missing index DMVs and query plans, there aren't any suggestions. 

Why is that?
Top Answer
meme (imported from SE)
There are many reasons why you may not have missing index requests!

We'll look at a few of the reasons in more detail, and also talk about some of the general limitations of the feature.

General Limitations

First, from: [Limitations of the Missing Indexes Feature][1]:

>  - It does not specify an order for columns to be used in an index.

As noted in this Q&A: [How does SQL Server determine key column order in missing index requests?][2], the order of columns in the index definition is dictated by Equality vs Inequality predicate, and then column ordinal position in the table. 

There are no guesses at selectivity, and there may be a better order available. It's your job to figure that out.
**Special Indexes**
Missing index requests also don't cover 'special' indexes, like:

 - Clustered
 - Filtered
 - Partitioned
 - Compressed
 - XML-ed
 - Spatial-ed
 - Columnstore-d
 - Indexed View-ed

What columns are considered?

Missing Index key columns are generated from columns used to filter results, like those in:

 - JOINs
 - WHERE clause

Missing Index Included columns are generated from columns required by the query, like those in:


Even though quite often, columns you're ordering by or grouping by can be beneficial as key columns. This goes back to one of the Limitations:

> - It is not intended to fine tune an indexing configuration.

For example, this query will not register a missing index request, even though adding an index on LastAccessDate would prevent the need to Sort (and spill to disk).

    SELECT TOP (1000) u.DisplayName
    FROM dbo.Users AS u
    ORDER BY u.LastAccessDate DESC;


Nor does this grouping query on Location.

    SELECT TOP (20000) u.Location
    FROM dbo.Users AS u
    GROUP BY u.Location


That doesn't sound very helpful!

Well, yeah, but it's better than nothing. Think of missing index requests like a crying baby. You know there's a problem, but it's up to you as an adult to figure out what that problem is.

You still haven't told me why I don't have them, though...

Relax, bucko. We're getting there.

Trace Flags

If you enable [TF 2330][5], missing index requests won't be logged. To find out if you have this enabled, run this:


Index Rebuilds

[Rebuilding indexes][6] will clear missing index requests. So before you go Hi-Ho-Silver-Away rebuilding every index the second an iota of fragmentation sneaks in, think about the information you're clearing out every time you do that.

You may also want to think about [Why Defragmenting Your Indexes Isn’t Helping][7], anyway. Unless you're using [Columnstore][8].

Adding, Removing, or Disabling Indexes
Adding, removing, or disabling an index will clear all of the missing index requests for that table.  If you're working through several index changes on the same table, make sure you script them all out before making any.

Trivial Plans

If a plan is simple enough, and the index access choice is obvious enough, and the cost is low enough, you'll get a trivial plan. 

This effectively means there were no cost based decisions for the optimizer to make.

Via [Paul White][9]:

>  The details of which types of query can benefit from Trivial Plan change frequently, but things like joins, subqueries, and inequality predicates generally prevent this optimization.

When a plan is trivial, additional optimization phases are not explored, and [missing indexes are not requested][10].

See the difference between these queries and [their plans][11]:

    SELECT *
    FROM dbo.Users AS u
    WHERE u.Reputation = 2;
    SELECT *
    FROM dbo.Users AS u
    WHERE u.Reputation = 2
    AND 1 = (SELECT 1);


The first plan is trivial, and no request is shown. There may be cases where bugs prevent missing indexes from appearing in query plans; they are usually more reliably logged in the missing index DMVs, though.


Predicates where the optimizer wouldn't be able to use an index efficiently even with an index may prevent them from being logged.

Things that are generally not SARGable are:

 - Columns wrapped in functions
 - Column + SomeValue = SomePredicate
 - Column + AnotherColumn = SomePredicate 
 - Column = @Variable OR @Variable IS NULL


    SELECT *
    FROM dbo.Users AS u
    WHERE ISNULL(u.Age, 1000) > 1000;

    SELECT *
    FROM dbo.Users AS u
    WHERE DATEDIFF(DAY, u.CreationDate, u.LastAccessDate) > 5000

    SELECT *
    FROM dbo.Users AS u
    WHERE u.UpVotes + u.DownVotes > 10000000

    DECLARE @ThisWillHappenWithStoredProcedureParametersToo NVARCHAR(40) = N'Eggs McLaren'
    SELECT *
    FROM dbo.Users AS u
    WHERE u.DisplayName LIKE @ThisWillHappenWithStoredProcedureParametersToo 
          OR @ThisWillHappenWithStoredProcedureParametersToo IS NULL;

None of these queries will register missing index requests. For more information on these, check out the following links:

 - [Optional Parameters and Missing Index Requests](https://www.brentozar.com/archive/2017/09/optional-parameters-missing-index-requests/)
 - [SARGable WHERE clause for two date columns](https://dba.stackexchange.com/questions/132437/sargable-where-clause-for-two-date-columns)
 - [What are different ways to replace ISNULL() in a WHERE clause that uses only literal values?](https://dba.stackexchange.com/questions/168276/what-are-different-ways-to-replace-isnull-in-a-where-clause-that-uses-only-lit)

You Already Have An Okay Index

Take this index:

`CREATE INDEX ix_whatever ON dbo.Posts(CreationDate, Score) INCLUDE(OwnerUserId);`

It looks okay for this query:

    SELECT p.OwnerUserId, p.Score
    FROM dbo.Posts AS p
    WHERE p.CreationDate >= '20070101'
    AND   p.CreationDate < '20181231'
    AND   p.Score >= 25000
    AND 1 = (SELECT 1)
    ORDER BY p.Score DESC;

The plan is a simple Seek...


But because the leading key column is for the less-selective predicate, we end up doing more work than we should:

> Table 'Posts'. Scan count 13, logical reads 136890

If we change the index key column order, we do a lot less work:

`CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);`


And significantly fewer reads:

> Table 'Posts'. Scan count 1, logical reads 5

SQL Server Is Creating Indexes For you

In certain cases, SQL Server will choose to create an index on the fly via an index spool. When an index spool is present, a missing index request won't be. Surely adding the index yourself could be a good idea, but don't count on SQL Server helping you figure that out.


  [1]: https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms345485(v=sql.105)
  [2]: https://dba.stackexchange.com/questions/208947/how-does-sql-server-determine-key-column-order-in-missing-index-requests
  [3]: https://i.stack.imgur.com/jAZhj.jpg
  [4]: https://i.stack.imgur.com/OksAJ.jpg
  [5]: https://www.brentozar.com/archive/2015/11/trace-flag-2330-who-needs-missing-index-requests/
  [6]: https://littlekendra.com/2016/05/18/index-usage-stats-bug-fixed-in-sql-server-2012-sp2-cu12-sp3-cu3/
  [7]: https://groupby.org/conference-session-abstracts/why-defragmenting-your-indexes-isnt-helping/
  [8]: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2016/03/07/columnstore-index-defragmentation-using-reorganize-command/
  [9]: http://sqlblog.com/blogs/paul_white/archive/2012/04/28/query-optimizer-deep-dive-part-1.aspx
  [10]: https://www.brentozar.com/archive/2013/07/dude-who-stole-my-missing-index-recommendation/
  [11]: https://www.brentozar.com/pastetheplan/?id=BkPun7YFX
  [12]: https://i.stack.imgur.com/4tTLd.jpg
  [13]: https://i.stack.imgur.com/oVu5D.jpg
  [14]: https://i.stack.imgur.com/fWnL2.jpg
  [15]: https://i.stack.imgur.com/Xu2e4.png

This room is for discussion about this question.

Once logged in you can direct comments to any contributor here.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.