Index Hinting in Platform Update for Microsoft Dynamics NAV 4.0 SP3 KB940718

Introduction

On SQL Server, you can use index hinting to force the server to use a particular index when executing queries for FINDFIRST, FINDLAST, FINDSET, FIND('-'), FIND('+'), FIND('=') and GET statements. Queries generated by the form runtime will be affected by index hints in the same way.

Index hinting can help avoid situations where SQL Server’s Query Optimizer chooses an index access method that requires many page reads and generates long-running queries with response times that vary from seconds to several minutes. Directing SQL Server to use a specific index can give instant 'correct' query executions with response times of milliseconds.

In Microsoft Dynamics NAV, index hinting is turned on by default and the application automatically uses this functionality to improve performance.

If you need to switch off or customize index hinting to fit your implementation, you must create a SQL Server table to store the configuration parameters. The parameters you enter into this table will determine some of the behavior of Microsoft Dynamics NAV when it is using this database.

In the database create a table, owned by dbo:

CREATE TABLE [$ndo$dbconfig] (config VARCHAR(512) NOT NULL)

GRANT SELECT ON [$ndo$dbconfig] TO public

(You can add additional columns to this table, if necessary. The length of the config column should be large enough to contain the necessary configuration values, as explained in the following, but need not be 512.)

The default value is IndexHint=Yes.

You can disable index hinting at any level of granularity.

There are two ways of using index hinting in your application:

· You can leave index hinting turned on and disable it in specific places.

· You can turn off index hinting and enable it in specific places.

Benefits

Index hinting has been shown to optimize performance in the following scenarios:

1. Index hints prevent SQL Server from using an out of date query plan, such as a clustered index scan.

2. Index hints prevent SQL Server from scanning smaller tables and escalating locks to table locks.

Consequences

SETCURRENTKEY must correspond to the filter that you want to place on the table.

GLEntry.SETCURRENTKEY(GLEntry.AccountNo);
//Should be added to the code if not already present
GLEntry.SETRANGE(GLEntry.AccountNo,’1000’,’9999’);
GLEntry.FINDSET();

Example:
In the following C/AL code, index hinting is turned on but SETCURRENTKEY has not been used:

GLEntry.SETRANGE("G/L Account No.",'2910');
GLEntry.FINDSET;

This will generate the following SQL query:

SELECT TOP 500 * FROM "W1403"."dbo"."CRONUS International Ltd_$G_L Entry" WITH (READUNCOMMITTED, INDEX("CRONUS International Ltd_$G_L Entry$0")) WHERE (("G_L Account No_"=@P1)) ORDER BY "Entry No_" ','2910'

Note that without a SETCURRENTKEY, Microsoft Dynamics NAV will hint the SQL index which corresponds to the primary key in the G/L Account table. This is not the best key to use for this query.

Conversely, in the following C/AL code, hinting is turned on and SETCURRENTKEY has been used:

GLEntry.SETCURRENTKEY("G/L Account No.");
GLEntry.SETRANGE("G/L Account No.",'2910');
GLEntry.FINDSET;

This will generate the following SQL query:

SELECT TOP 500 * FROM "W1403"."dbo"."CRONUS International Ltd_$G_L Entry" WITH (READUNCOMMITTED, INDEX("$1")) WHERE (("G_L Account No_"=@P1)) ORDER BY "G_L Account No_","Posting Date","Entry No_" ','2910'

Now, because the C/AL code specifies which key to use, Microsoft Dynamics NAV hints the corresponding index from the code, which ensures that the right index is always used.

If you turn index hinting off, Microsoft SQL Server will define the index automatically.

Disabling Index Hinting in Specific Places

Index hinting is turned on by default but you can disable index hinting for a specific company, table or index.

Here are a few examples that illustrate how to disable index hinting by executing a statement in query analyzer:

Example 1 (Index hinting is turned off across the entire application)

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=No’)

Example 2 (Index hinting is turned off for the Cronus International Ltd. company only.)

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=No;Company="CRONUS International Ltd."’)

Example 3 (Index hinting is turned off for the Sales Header table only.)

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=No;Company="CRONUS International Ltd.";Table="Sales Header')

Example 4 (Index hinting is turned off for the $1 index in the Sales Header table only.)

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=No;Company="CRONUS International Ltd.";Table="Sales Header";Index="1"')

Enabling Index Hinting in Specific Places

As mentioned earlier, you can disable index hinting for the entire system and then enable it where appropriate for your application.

The index hint syntax is:

IndexHint=<Yes,No>;Company=<company name>;Table=<table name>;Key=<keyfield1,keyfield2,...>; Search Method=<search method list>;Index=<index id>

Each parameter keyword can be localized in the "Driver configuration parameters" section of the .stx file.

The guidelines for interpreting the index hint are:

• If a given keyword value cannot be matched the entry is ignored.

• The values for the company, table, key fields and search method must be surrounded by double-quotes to delimit names that contain spaces, commas etc.

• The table name corresponds to the name supplied in the Object Designer (not the Caption name).

• The Key must contain all the key fields that match the required key in the Keys window in the Table Designer.

• Search Method contains a list of search methods used in FIND statements:

Function

Symbol

RECORD.GET()

!

RECORD.FIND()

=

RECORD.FIND(‘-‘)

-

RECORD.FIND(‘+’)

+

RECORD.FIND(‘>’)/RECORD.NEXT()

>

RECORD.FIND(‘<’)/RECORD.PREV()

<

RECORD.FINDFIRST()

[

RECORD.FINDLAST()

]

RECORD.FINDSET()

$

                

• The index ID corresponds to a SQL Server index for the table: 0 represents the primary key; all other IDs follow the number included in the index name for all the secondary keys. Use the SQL Server command sp_helpindex to get information about the index ID associated with indexes on a given table. In this example we are looking for index information about the Item Ledger Entry table:

sp_helpindex 'CRONUS International Ltd_$Item Ledger Entry'

When Dynamics NAV executes a query, it checks whether or not the query is for the company, table, current key and search method listed in one of the IndexHint entries. If it is, it will hint the index for the supplied index ID in that entry.

Note that:

• If the company is not supplied, the entry will match all the companies.

• If the search method is not supplied, the entry will match all the search methods.

• If the index ID is not supplied, the index hinted is the one that corresponds to the supplied key. This is probably the desired behavior in most cases.

• If the company/table/fields are renamed or the table's keys redesigned, the IndexHint entries must be modified manually.

Here are a few examples that illustrate how to add an index hint to the table by executing a statement in Query Analyzer:

Example 1

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=Yes;Company="CRONUS International Ltd.";Table="Item

Ledger Entry";Key="Item No.","Variant Code";Search Method="-

+";Index=3')

This hint will use the $3 index of the CRONUS International Ltd_$Item Ledger Entry table for FIND('-') and FIND('+') statements when the Item No.,Variant Code key is set as the current key for the Item Ledger Entry table in the CRONUS International Ltd. company.

Example 2

INSERT INTO [$ndo$dbconfig] VALUES

 ('IndexHint=No;Company="CRONUS International Ltd.";Table="Item

Ledger Entry";Key="Item No.","Variant Code";Search Method="-

+";Index=3')

The index hint entry is disabled.

Example 3

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=Yes;Company="CRONUS International Ltd.";Table="Item

Ledger Entry";Key="Item No.","Variant Code";Search Method="-

+";Index=')

This will hint the use of the Item No.,Variant Code index of the CRONUS International Ltd_$Item Ledger Entry table for FIND('-') and FIND('+') statements when the Item No.,Variant Code key is set as the current key for the Item Ledger Entry table in the CRONUS International Ltd. company.

This is probably the way that the index-hinting feature is most commonly used.

Example 4

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=Yes;Company=;Table="Item Ledger Entry";Key="Item

No.","Variant Code";Search Method="-+";Index=3')

This will hint the use of the $3 index of the CRONUS International Ltd_$Item Ledger Entry table for FIND('-') and FIND('+') statements when the Item No.,Variant Code key is set as the current key for the Item Ledger Entry table for all the companies (including a non-company table with this name) in the database.

Example 5

INSERT INTO [$ndo$dbconfig] VALUES

('IndexHint=Yes;Company="CRONUS International Ltd.";Table="Item

Ledger Entry";Key="Item No.","Variant Code";Search Method=;Index=3')

This will hint the use of the $3 index of the CRONUS International Ltd_$Item Ledger Entry table for every search method when the Item No.,Variant Code key is set as the current key for the Item Ledger Entry table in the CRONUS International Ltd. company.

Note: It requires a developer license to change C/AL code in Microsoft Dynamics NAV. It is highly recommended to have the changes evaluated and implemented by a Microsoft Dynamics NAV partner.

These postings are provided "AS IS" with no warranties and confer no rights. You assume all risk for your use.