Advertisement
However, when planning this month’s commentary, I went back and reread what I wrote last month and realized I hadn’t even mentioned one of the new features I had thought would be the easiest and most straightforward to talk about—the new index hints, including FORCESCAN and enhancements to FORCESEEK. I have always found optimizer hints to be a very interesting topic for a couple of reasons. Not too many versions ago, the SQL Server team at Microsoft seemed to imply that as the optimizer got better and smarter, the need for hints in your queries should practically disappear. Instead, they started adding more and more hints so that now there are more than two dozen table hints and almost the same number of query hints. I actually call the query hints “option hints” because they’re specified in the OPTION clause, and I think that all hints are query hints. Plus, as of SQL Server 2008, most of the table hints can be specified as an OPTION hint. So it’s pretty obvious that hints aren’t going away any time soon because more and more are added in each new version and sometimes in between versions. (In fact, the FORCESCAN hint that many people list as a new SQL Server 2012 feature was actually added in SQL Server 2008 R2 SP1.)
The second reason I find the whole subject of hints to be fascinating is that at first glance, a lot of less-experienced SQL Server users think that hints will make their jobs easier. They think it is easier to get the performance they’re looking for in their queries if they can specify how SQL Server should process those queries. But, of course, those of you with just a bit more experience are well aware that the truth is just the opposite. To use hints effectively, you really need to understand a lot about how SQL Server works and why one plan might be better or worse than another. In fact, some of the worst performance you might ever encounter could arise when a hint is used to force SQL Server to use an index seek in a case in which the query is going to return a very large number of rows. Many people think that one of the worst steps in a query plan is a table scan, but in my experience, using a nonclustered index seek inappropriately can give far worse performance. Here’s quick example. In the AdventureWorks2008 sample database, there’s a table called Sales.SalesOrderHeader with a nonclustered index on the column CustomerID. If we run a query that returns only a few rows, the nonclustered index is a good choice. The following query returns 33 rows (out of 31,465 in the table). uses the nonclustered index, and requires 112 logical reads:
SET STATISTICS IO ON
SELECT * FROM Sales.SalesOrderHeader
WHERE CustomerID < 11011;
SELECT * FROM Sales.SalesOrderHeader
WHERE CustomerID < 11011;
SELECT *
FROM Sales.SalesOrderHeader WITH (FORCESEEK, INDEX (IX_SalesOrderHeader_CustomerID))
WHERE CustomerID < 12022;
FROM Sales.SalesOrderHeader WITH (FORCESEEK, INDEX (IX_SalesOrderHeader_CustomerID))
WHERE CustomerID < 12022;
SELECT *
FROM Sales.SalesOrderHeader WITH (FORCESCAN, INDEX (0))
WHERE CustomerID < 11011;
FROM Sales.SalesOrderHeader WITH (FORCESCAN, INDEX (0))
WHERE CustomerID < 11011;
SELECT *
FROM Sales.SalesOrderHeader WITH (FORCESCAN, INDEX (PK_SalesOrderHeader_SalesOrderID))
WHERE CustomerID < 11011;
FROM Sales.SalesOrderHeader WITH (FORCESCAN, INDEX (PK_SalesOrderHeader_SalesOrderID))
WHERE CustomerID < 11011;
There are many more subtleties to using index hints, both in the enhancements in SQL Server 2012 and in the use of hints in general. But the biggest hint I can give you for effective use of hints is to learn all you can about tuning SQL Server queries and about the SQL Server optimizer. Also, search for blog posts about SQL Server hints; I recommend starting here.

