Tuesday, 20 May 2014

Index

What is an index?
Before we start talking about indexes, let’s think about the a question: What is an index?
Take a look at the yellow papers; there are millions of phone numbers in it, and they are categorized on City, Business, Business type etc. If you want to find something, you look into the categorized area; there you find some information with a page number. Next you find the page, and start reading this page till you find the thing you need. This categorized information acts the same like an index, and reading the page till you find what you needed is called a page scan. So when I have a phone number and I need the business that belongs to that number, I have to read all the pages of the yellow pages till I have found it. There is simply no support of categorized items. This scanning of the complete yellow pages is called a table scan in a database.
But what will happen if I get new business information into my yellow pages.  Or the name of a business has changed. My categorized area needs to be update for giving correct information. In a database we call this reindexing This reindexing can become heavy if the data has to be moved from on page to another page. This is also the reason why fields of an index value should have the property allow edit on create.
A highly optimized index is a cluster index, there is no additional storage, and the data is stored physical in the correct order.  If we look closely at the physical storage of a clustered index, we see that the data is grouped in pages; every page belongs to an index key value. When we have a lot of inserts into a clustered indexed table we get also performance issues. The database has some free space between the pages, but when this free space is consumed, the storage of the data gets fragmented into the database. Reindexing the database can solve this.
In general, an index knows on which page in the SQL database the record exists. By using indexes only the SQL database pages that have related information, are scanned to find the record. So let’s pretend we have an index on a Boolean field of a table.  The records with yes and no values exist on all pages, so the index will use all pages. (Index scan)
Types of Indexes
There are mainly 2 types of indexes which are as follows:
Clustered Index – A clustered index is a special type of index that arranges the way records in the table are physically stored. You can create only a single clustered index against one or more columns of a table or a view. A maximum of 16 columns can be a part of a clustered index. A clustered index is identified in the sys.partitions table and has an Index_ID value of ‘1’. When Clustered indexes are created a B-Tree structure is created and the leaf nodes of a B-Tree contain the data pages.
Non Clustered Index – A nonclustered index is a special type of index in which the logical order of the index does not match the physical stored order of the rows on disk. When Non Clustered indexes are created a B-Tree structure is created and the leaf node of a B-Tree of a nonclustered index does not consist of the data pages. Instead, the leaf nodes contain a pointer to the data pages. You can create up to 249 nonclustered indexes for a table or a view. These indexes are created to support the queries that are used to retrieve data from a table or a view. A nonclustered index is identified in the sys.partitions table with anIndex_ID value of 2 to 250.
A table which has no Clustered Index is referred to as a Heap.
It becomes important to know the basics of how indexes work as a correct index will boost performance and a wrong index will drastically reduce performance.
select * from sys.indexes ind where ind.object_id = (select OBJECT_ID from sys.tables tab where  tab.name = ‘CustTable’)
Note the column ‘type_desc’ which gives the type of Index in CustTable. The same indexes can be viewed within the AOT as shown in Figure 2. However the levels of details shown in SSMS are more and are required by administrators to get details on Indexes. Dynamics AX Kernel by default adds the RecId as a Non Clustered Index which can be seen from SSMS.
How Indexes Improve Performance
Indexes can optimize not only SELECT, but also UPDATE and DELETE statements. The reason is that the SQL Server must find the records prior to modifying or deleting them. Keep in mind however, that SQL Server has to maintain clustered and non-clustered indexes every time data is INSERTED, UPDATED or DELETED. Having numerous indexes on a table can cause significant overhead on the SQL Server during data modifications.
When a query is sent to SQL Server, the query optimizer comes up with the most efficient execution plan. SQL Server does not have to use an index to satisfy a query; in fact, if it is quicker to scan the entire table, SQL Server will do so. Usually if a query requires returning more than about 1% of table rows and there is no covering index, it is quicker to scan the whole table than to seek on the nonclustered and then lookup the missing columns from the clustered index/heap.
The popular understanding is that adding more indexes to a table will improve performance but this is not true. In fact over-indexing can degrade performance drastically. So how do we know how many indexes to add and where the thin line is which differentiates between over- & under-indexing? Well, there is no magic formula for defining the number of indexes but it depends on a lot of important factors like data type in the tables, work load, query structure etc.  With CRUD statements, indexes undergo fragmentation and when the level of fragmentation increases above a threshold the query performance degrades. We will be discussing more on index fragmentation later on in this chapter.
Indexes in Dynamics AX
Indexes are created inside AX in the AOT Tables Node. Prior to index creation, index design has to be done as to determine the columns we want to index, what type of index we should consider, the number of columns in an index and the queries which we will use. It is relatively easy to create indexes inside AX, but some pointers must be kept in mind.
  • Do the task of index design diligently. There is no magic formula which will tell you the number of indexes you must create for a table. You must work out and consider all possible scenarios.
  • Ensure that you select the Primary Index & Cluster Index property in the Table Property sheet as shown below.
  • Apart from properly indexing tables, also consider table caching properties to improve performance.
  • Ensure all tables have a Cluster Index and a Primary Key.
  • Reduce the number of fields in queries
  • Monitor indexes and ensure that unused indexes are removed.
Apart from these tips, there are some best practices which will help you decide what indexes to create in AX. These are discussed under the best practices section in this chapter.
Best Practices for Index creation in AX
  • Keep indexes lean. Try to build indexes on one or few columns. Wide indexes take longer to scan than narrow indexes.
  • The number of indexes on a table should not be very high. Usually 7-9 indexes in a standard Master, Transaction table is recommended. For Setup & Parameter tables, limit the number of indexes to the important columns only.
  • Create a clustered index on every table. However, choose the column(s) for the clustered index judiciously.
  • Try to create the clustered index on the column which is used most frequently for retrieving data.
  • Try to create the clustered index on the column with high selectivity; that is the column that does not have many duplicate values.
  • Try to create the clustered index on the column that will never be updated or will be updated infrequently. Every time the clustered index key is updated, SQL Server must maintain not just the clustered index but also the non-clustered indexes since non-clustered indexes contain a pointer to the clustered index. This is yet another reason why you shouldn’t create the clustered index on multiple columns.
  • By default, SQL Server creates the clustered index on the PRIMARY KEY column(s) unless the clustered index is created prior to creating the primary key. It is often beneficial to have the clustered index on the primary key, but sometimes you’re better off saving the clustered index for other column(s
  • SQL Server has to perform some maintenance when index keys are updated, so each additional index could impose a slight performance penalty on the performance of INSERT, UPDATE and DELETE statements. Nevertheless the cost of index maintenance could be far less than the performance improvement you’ll reap for your SELECT statements.
  • Be sure to eliminate duplicate indexes, that is, multiple indexes created on the same set of columns. Such indexes provide no additional benefit but use up extra disk space and might hinder performance of INSERT, UPDATE and DELETE statements.
  • Check the default fill factor level configured at the server level. To control the rate of fragmentation of an index, you can use an index option called the fill factor. Modifying fill-factor is a DBA task and must be done carefully. For Dynamics AX the recommended value is 80%. You can enable this from the UI or use the CREATE INDEX or ALTER INDEX statements to set the fill-factor value for individual indexes. To modify the server-wide default value, use the sp_configure system stored procedure. To view the fill-factor value of one or more indexes, use sys.indexes.

Fill factor only affects the leaf nodes. For the intermediate nodes please refer to PAD_INDEX.

No comments:

Post a Comment