SQL SERVER – Introduction to Basics of a Query Hint – A Primer

SQL SERVER - Introduction to Basics of a Query Hint - A Primer book3 This blog post is inspired from SQL Architecture Basics Joes 2 Pros: Core Architecture concepts – SQL Exam Prep Series 70-433 – Volume 3.

[Amazon] | [Flipkart] | [Kindle] | [IndiaPlaza]


Basics of a Query Hint

Query hints specify that the indicated hints should be used throughout the query. Query hints affect all operators in the statement and are implemented using the OPTION clause.

The basic syntax structure for a Query Hint is shown below:

DECLARE @Type VARCHAR ( 50 )
SET @Type = 'Business'
SELECT *
FROM Customer
WHERE CustomerType = @Type
OPTION ( OPTIMIZE FOR ( @Type = 'Business' ));


Cautionary Note:

Because the SQL Server Query Optimizer typically selects the best execution plan for a query, it is highly recommended that hints be used as a last resort for experienced developers and database administrators to achieve the desired results.

Create an Index for improved Optimization

In the following examples the Customer Table has had a non-clustered index placed on the CustomerType field, as shown in the screenshot below:

SQL SERVER - Introduction to Basics of a Query Hint - A Primer j2p-day3-image-1

This index should help query performance if the query is selective enough. That is, if the Query Optimizer gets the right information in time to make this kind of a decision it will perform a Seek which is much faster than a Scan. Variables often confuse the Query Optimizer in certain ways. You will see this demonstrated in the next exercise.

Expecting a Seek and getting a Scan

SQL Server is actually smart enough to take the exact same index and realize, through statistics, which of these criteria is selective and which is not. You have seen in the previous example that it is possible to accidentally trick the Query Optimizer into making the wrong decision.

First declare a variable named @Type, which is a varchar (50) and Set it equal to ‘Consumer’. This variable will be part of the predicate. Run the query with the variable set to ‘Consumer’ and you get 773 records. Change the @Type variable to ‘Business’ and you get a selective query which returns two records. See both figures below.

SQL SERVER - Introduction to Basics of a Query Hint - A Primer j2p-day3-image-2a

SQL SERVER - Introduction to Basics of a Query Hint - A Primer j2p-day3-image-2b

The query that predicates on ‘Consumer’ is better off scanning since it’s pulling almost all of the records from the entire table.

SQL SERVER - Introduction to Basics of a Query Hint - A Primer j2p-day3-image-3a

However, the query that predicates on ‘Business’ is a very selective query covered by the NCI_Customer_CustomerType index. Thus, you might be shocked to see that it is still a Scan instead of the anticipated Seek.

SQL SERVER - Introduction to Basics of a Query Hint - A Primer j2p-day3-image-3b

The Query Optimizer doesn’t know what value the @Type variable holds until runtime, and does not check statistics for variables before a query runs. When in doubt, the Query Optimizer will always choose a scan.

Implementing the Query Hint

When predicating on values from variables you may need to give the query a hint, letting the Query Optimizer know the best way to execute the query. If your @Type variable is most often set to the value of ‘Business’ it would be smarter to optimize this query to perform a Seek based on this value.

To do this, you will need to add some additional code to your query, shown in the screenshot below:

SQL SERVER - Introduction to Basics of a Query Hint - A Primer j2p-day3-image-4

Excellent! The Query Execution Plan now indicates that it will use a Seek to perform this query and your work is done.


This blog post is inspired from SQL Architecture Basics Joes 2 Pros: Core Architecture concepts – SQL Exam Prep Series 70-433 – Volume 3.

[Amazon] | [Flipkart] | [Kindle] | [IndiaPlaza]

Reference: Pinal Dave (https://blog.sqlauthority.com)

Joes 2 Pros, SQL Scripts
Previous Post
SQL SERVER – Introduction to Hierarchical Query using a Recursive CTE – A Primer
Next Post
SQL SERVER – Introduction to SQL Error Actions – A Primer

Related Posts

8 Comments. Leave new

  • If I have another Customer Type Visiting with almost same row of Business type then Can I add another Hint
    option(Optimize for (@type=’visting’))

    Reply
  • Hi Pinal,
    I have applied the same what you explained in the above, still it is going for scan. I am using Sql server 2005.

    Reply
  • Hi ,
    I am trying to get xml from a location into a table using rowset, the following is the query, but n but its not accepting as valid fiile name. Please help me
    CREATE TABLE #XmlImportTest(
    xmlFileName VARCHAR(300) NOT NULL,
    xml_data XML NOT NULL
    )
    GO
    declare @directory varchar(256) set @directory = ‘”D:\To Folder”‘

    declare @filecount int, @fileindex int, @linecount int, @lineindex int
    declare @filename varchar(255), @arg varchar(512), @contents varchar(8000)
    set @filename = ‘D:\To Folder’
    set @arg = ‘dir ‘ + @directory + ‘\ /A-D /B’
    declare @dir table (id int not null identity(1,1),[filename] varchar(512))
    insert @dir exec master.dbo.xp_cmdshell @arg
    DECLARE @ID int
    DECLARE IDs CURSOR LOCAL FOR select id from @dir
    OPEN IDs
    FETCH NEXT FROM IDs into @ID
    WHILE @@FETCH_STATUS = 0
    BEGIN
    SET @filename = @filename + ‘\’+ (select filename from @dir where id = @ID)

    print @filename
    declare @files table ([xmlFileName] varchar(512), [xml_data] xml null)

    INSERT INTO @files(xmlFileName, xml_data)

    SELECT ”’ + @filename + ”’, xmlData
    FROM(
    SELECT *
    FROM OPENROWSET (BULK ”’ + @filename +”’, SINGLE_BLOB) AS XMLDATA
    ) AS FileImport (XMLDATA)

    FETCH NEXT FROM IDs into @ID
    END
    CLOSE IDs
    DEALLOCATE IDs

    Reply
  • Hi ,
    I am trying to get xml from a location into a table using rowset, the following is the query, but n but its not accepting as valid fiile name. Please help me
    CREATE TABLE #XmlImportTest(
    xmlFileName VARCHAR(300) NOT NULL,
    xml_data XML NOT NULL
    )
    GO
    declare @directory varchar(256) set @directory = ‘”D:\To Folder”‘

    declare @filecount int, @fileindex int, @linecount int, @lineindex int
    declare @filename varchar(255), @arg varchar(512), @contents varchar(8000)
    set @filename = ‘D:\To Folder’
    set @arg = ‘dir ‘ + @directory + ‘\ /A-D /B’
    declare @dir table (id int not null identity(1,1),[filename] varchar(512))
    insert @dir exec master.dbo.xp_cmdshell @arg
    DECLARE @ID int
    DECLARE IDs CURSOR LOCAL FOR select id from @dir
    OPEN IDs
    FETCH NEXT FROM IDs into @ID
    WHILE @@FETCH_STATUS = 0
    BEGIN
    SET @filename = @filename + ‘\’+ (select filename from @dir where id = @ID)

    print @filename
    declare @files table ([xmlFileName] varchar(512), [xml_data] xml null)

    INSERT INTO @files(xmlFileName, xml_data)

    SELECT ”’ + @filename + ”’, xmlData
    FROM(
    SELECT *
    FROM OPENROWSET (BULK ”’ + @filename +”’, SINGLE_BLOB) AS XMLDATA
    ) AS FileImport (XMLDATA)

    FETCH NEXT FROM IDs into @ID
    END
    CLOSE IDs
    DEALLOCATE IDs

    Reply

Leave a Reply