Table Hint May Not Be Used By Query Optimizer
Developers should note that even though you specify a table-level hint in your
code, the query optimizer may ignore the hint. Table-level hints will be ignored
if the table is not chosen by the query optimizer and used in the subsequent query
plan. The query optimizer will often choose an indexed view over a table and in
case your table-level hint will be ignored, you can override the query optimizer's
preference for indexed views by using the OPTION (EXPAND VIEWS) query hint. Another
reason the query optimizer may ignore your hint is due to the fact that the table
may contain computed columns and the computed columns are computed by expressions
and functions referencing columns in other tables and the table hints are not
specified for those tables.
Table hints are not propagated on tables with computed columns so the hint
will not be used on tables referenced by computed columns, table-level hints are
propagated on base tables and views referenced by another view though. SQL Server
also does not allow more than one table hint from either the Granularity hint
group (PAGLOCK, NOLOCK, ROWLOCK, TABLOCK, and TABLOCKX) or the Isolation Level
hint group (HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD, and SERIALIZABLE)
to be used in the FROM clause for each table. This basically means that you cannot
specify ROWLOCK and TABLOCK for a table in the same FROM clause. SQL Server will
also not allow the NOLOCK, READUNCOMMITTED, or READPAST hints to be used against
tables that are the targets of a DELETE, INSERT or UPDATE statement.
Table Hint Syntax
Now that we have mentioned most of the hints lets look at the syntax for table-level
hints as used with the FROM clause.
SYNTAX
[ FROM { < table_source > } [ ,...n ] ]
< table_source > ::=
table_name [ [ AS ] table_alias ] [ WITH ( < table_hint > [ ,...n ] ) ]
< table_hint > ::=
{ INDEX ( index_val [ ,...n ] )
| FASTFIRSTROW
| HOLDLOCK
| NOLOCK
| PAGLOCK
| READCOMMITTED
| READPAST
| READUNCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
}
Microsoft encourages the use of the WITH keyword even though it is optional as
they state that a future release of SQL Server may require this keyword. Microsoft
also encourages the use of the optional commas between different hints as spaces
are only allowed for backward compatibility reasons. You can see that there are
fifteen hints defined in this syntax listing. Thirteen of those hints (HOLDLOCK,
NOLOCK, PAGLOCK, READCOMMITTED, READPAST, READUNCOMMITTED, REPEATABLEREAD, ROWLOCK,
SERIALIZABLE, TABLOCK, TABLOCKX, UPDLOCK, XLOCK) are considered table-level locking
hints while (INDEX and FASTFIRSTROW) are considered table hints. Doesn't mean
much to most developers, but I thought I would tell you how Microsoft groups them.
Table Hint Descriptions
Now that you know the names of the hints, how there grouped and the syntax of
each, lets go over what each hint does. INDEX is used to specify the name or object
ID of an index or indexes that will be used by SQL Server when processing the
statement. SQL Server will chose an index by default if one is not specified by
the use of the INDEX keyword, but sometimes you will need to force SQL Server
to use a particular index. Only one index hint can be used per table, but you
can specify more than one index in this hint. If a clustered index exists on the
specified table using INDEX(0) will force a clustered index scan and INDEX(1)
will force a clustered index scan or seek. If no clustered index exists on the
table then INDEX(0) will force a table scan while INDEX(1) will be interpreted
as an error. If you chose multiple indexes to be used for the hint, any duplicates
will be ignored.
Be careful in the order you place indexes when you use multiple indexes with
the index hint. SQL Server try to apply as many conditions as possible on each
index so if you place the broader indexes first you may have all your conditions
covered and SQL Server will not have to create AND statements for all the specified
indexes. You can use a maximum of 250 non-clustered indexes in an index hint.
Be aware that if an index hint with multiple specified indexes is used on a fact
table in a star join, then SQL Server will ignore will return a warning message
and ignore the hint. FASTFIRSTROW will optimize the query to retrieve the first
row of the result set. HOLDLOCK (equivalent to SERIALIZABLE) will apply only to
the table specified and only for the duration of the transaction and will hold
a shared lock for this duration instead of releasing it as soon as the required
table, data page, row or data is no longer required. HOLDLOCK cannot be used in
a SELECT statement with the FOR BROWSE option specified. NOLOCK (equivalent to
READUNCOMMITTED) will dirty reads.
Join our new forums at WebProWorld! Ask
your toughest questions or help your peers solve their issues. |
|
Dirty reads will not issue shared locks and will ignore exclusive locks placed
by other processes. It is possible to receive error messages if the read takes
place on an uncommitted transaction or a set of pages being rolled back. PAGLOCK
will force the use of a page lock instead of a table lock. READCOMMITTED will
specifies that shared locks are held while the data is being read to avoid dirty
reads but the data can be changed before the end of the transaction, which will
result in nonrepeatable reads and may cause phantom data. READCOMMITTED is the
default table hint in SQL Server. READPAST will specify that locked rows be skipped
during the read. READPAST only applies to transactions operating at the default
READ COMMITTED isolation level and will only read past row-level locks. READPAST
can only be used in SELECT statements. Normal blocking can be worked around by
having transactions read past rows being locked by other transactions. READUNCOMMITTED
(equivalent to NOLOCK) will dirty reads. Dirty reads will not issue shared locks
and will ignore exclusive locks placed by other processes. It is possible to receive
error messages if the read takes place on an uncommitted transaction or a set
of pages being rolled back. REPEATABLEREAD will specify that locks be placed on
all data that is used in a query, preventing other users from updating the data,
but new phantom rows can be inserted into the data set by another user and are
included in later reads in the current transaction.
Click
Here to Read the Full Article
About the Author:
Randy has been working with SQL Server for over 6 years as both a development
and production DBA. His clients have ranged from small companies to large firms
dealing with 25 Terabytes of data with single databases approaching 2.5 Terabytes
in size. He is currently the author of Transact-SQL Language Reference Guide and
numerous SQL Server newsletter articles. You can find out more about his book
and works at http://www.transactsql.com.
Read this newsletter at: http://www.sqlpronews.com/2003/0821.html |
|