This is a follow up from an earlier blog "Finding Index usage". In that blog, I described a very simple way to list how indexes are being used. In this blog, the query is much extended so that it now shows your Navision keys, listed by either number of updates, or by their cost divided by their usage, and it shows when an index was last used for reading. The idea is to show a list of indexes that are being maintained, but never or rarely being used.
The query uses SQL Server Dynamic Managament Views (DMW), which means it will only work for for SQL Server 2005 and later.
Feel free to add comments to this blog about how useful (or not) this query is. And about any problems you may find, and suggestions to improve it. All comments will be welcome!
To use it, copy the query below into SQL Server Management Studio. Remember to set the database to your Microsoft Dynamics NAV database (not Master or any other database). Then run it. Depending on the size of your database, it may take a few minutes to run it. First time you run it, I would recommend that you do it when the SQL Server is not otherwise busy, until you konw how long it takes:
-- use NavisionDB
IF
-- Generate list of indexes with key list
create
[F_Obj_ID] [int]
[F_Obj_Name] [nvarchar]
[F_Ind_ID] [int]
[Index_Column_ID] [int]
[Index_Key] [nvarchar]
[Index_Key_List] [nvarchar]
[F_Obj_ID]
[F_Ind_ID]
[Index_Column_ID]
)
Insert
select
index_id
Index_Column_ID
from
go
-- populate key string
declare
FOR
DECLARE
set
open
fetch
while
end
close
deallocate
-- Generate list of Index usage
[F_Table_Name] [nvarchar]
[F_Index_Name] [nvarchar]
[No_Of_Updates] [int]
[User_Reads] [int]
[Last_Used_For_Reads] [datetime]
[Index_Type] [nvarchar]
[last_user_seek] [datetime]
[last_user_scan] [datetime]
[last_user_lookup] [datetime]
[Index_Keys] [nvarchar]
insert
object_name
US
SI
case
''
order
-- Select and join the two tables.
TIU
--TIU.F_Ind_ID Index_ID,
--TIU.F_Index_Name Index_Name,
TIK
and
--order by Cost_Benefit desc
The query will show you one line for each index in the SQL Database. It shows you the table name, and a list of fields in the index. Note that any non-clustered index also contain the clustered index. For example on SQL Server, the key "Document No." in the "Cus. Ledger Entry table" is "Document No.","Entry No.". Also note that the indexes shown by SQL Server is not always shown in the same order as you have defined them in NAV.
The column "No_Of_Updates" basically shows you the cost of this index, since every update requires a lock as well as a write to the database. The next column, "User_Reads", shows you how often this index has been used, either from the UI, or by C/AL code. Compare these two, and you have way to compare the cost against the benefits of each index, as shown in the column "Cost_Benefit", which is simply "No_Of_Updates" / "User_Reads". The column "Last_Used_For_Reads" shows you when an index was actually used for reading.
The query sorts the indexes by "No_Of_Updates", with the most updated (most costly) index first. At the last line of the query you can change the sorting to "order by Cost_Benefit desc", and you are likely to see a different picture.
Finally, the query shows you whether each index is clustered or non-clustered.
The query will create two new tables called "z_IUQ_Temp_Index_Keys" and "zIUQ_Temp_Index_Usage". Although highly unlikely, if you already have tables with these names in your database, then the query will overwrite those without warnings. These tables collect index usage statistics, so if you need to run the query again, for example because you lost the results, or wat to run it with a different sorting, you don't have to run the whole query. Just run the last part of the query - from the section "-- Select and join the two tables.", and it will run much faster. Only after you change indexes, or want an updated view of index usage, you need to run the whole query again.
The data shown by the query is reset every time SQL Server restarts. So if you have recently restarted SQL Server, then the query may not show you the most precise picture of how the indexes are being used over time. Also consider that some indexes may only ever be used for example at end of the month / end of fiscal year, etc. So just because the query shows that a certain index was not used since SQL Server was last restarted, then this index may still be required for specific jobs.
Lars Lohndorf-Larsen (Lohndorf)Escalation Engineer