Tag Archives: performance

Checking AX2009 ‘EntireTable’ Caching Setup

We are going to look at how you can review your ‘EntireTable’ Cache settings on tables within the AOT and why performance can be improved if your settings are incorrect.

When a table’s Cache Lookup in the AOT is set to ‘EntireTable’ it means a maximum of 2,000 records are loaded into the AOS servers cache for that table which saves having to go back to the SQL Server Database each time a query on that table is performed.

Each time a record is Inserted / Updated / Deleted the cache on the AOS has to be dropped and reloaded for that particular table, if you have a large table that is set to ‘EntireTable’ type caching and the table is being changed often this can cause detrimental effects on performance for your users as the table is having to be dropped from the cache and reloaded often and the AOS may have to go to back to the database anyway if the record isn’t in the cache.

We can check quite easily to see what tables are set in the AOT to ‘EntireTable’ caching and their associated row count in the database using the scripts below, I’ve provided two scripts one for real-time analysis and one which can be used with DynamicsPerf if you have this setup and configured for your environment:

Real-Time Analysis:

/* AX EntireTable Caching Row Counts (Real Time).sql
-- D.Coupland 24/03/13
-- Find rows counts of tables with cache lookup set to 'EntireCache' 
-- Investigate any row counts over 2,000+ to ensure they are not affecting performance

USE <MyDax09Database>

                        WHEN AOT.TABID BETWEEN 1 AND 7999 THEN 'SYS'
                        WHEN AOT.TABID BETWEEN 8001 AND 15999 THEN 'GLS'
                        WHEN AOT.TABID BETWEEN 16001 AND 17999 THEN 'DIS'
                        WHEN AOT.TABID BETWEEN 18001 AND 19999 THEN 'LOS'
                        WHEN AOT.TABID BETWEEN 20001 AND 29999 THEN 'BUS'
                        WHEN AOT.TABID BETWEEN 30001 AND 39999 THEN 'VAR'
                        WHEN AOT.TABID BETWEEN 40001 AND 49999 THEN 'CUS'
                        WHEN AOT.TABID BETWEEN 50001 AND 59999 THEN 'USR'
                        WHEN AOT.TABID >= 65000 THEN 'System Table'
                        ELSE Ltrim(Str(AOT.TABID))
AND AOT.CACHELOOKUP = 4 -- EntireTable Cache Enabled
AND ST.ROW_COUNT > 0 -- Ignore Tables with no rows

Using DynamicsPerf DB

/* AX EntireTable Caching Row Counts (Using DynamicsPerf DB).sql
-- D.Coupland 24/03/13
-- Find rows counts of tables with cache lookup set to 'EntireCache' 
-- Investigate any row counts over 2,000+ to ensure they are not affecting performance

USE <MyDynamicsPerfDB>

ISC.ROW_COUNT > 0  AND -- Ignore Tables with no rows
CACHE_LOOKUP = 'EntireTable' 

Download the scripts here: AX EntireTable Caching Row Counts (928 downloads)

I recommend you review any tables over 2,000+ rows in your ‘EntireTable’ caching strategy regularly ensuring you test any changes prior to making the changes in your Production Environment.

For further reading on AX 2009 Caching please take a look at the following articles:



Dynamics AX 2009 Tracing on Application Object Servers the easy way

Troubleshooting AX 2009 Performance Issues can be sometimes frustrating when you’ve got a lot of users using the system and you want to trace one particular users session.

One way that can ease this is to log the user onto an AOS where the service account it runs under is different to your other AOS’s and where they are the only user on the AOS. This means you can trace only their session using the “Microsoft Dynamics AX 2009 Server Configuration” application along with SQL Server Profiler (In Profiler you can specify the service account to be traced).

In order to set this up there are two different options, option 1 is the preferred option.

Option 1: Install a new AOS on an existing server that has the capacity or a new server – you can allocate specific CPU’s for each AOS Service on your server within the “Microsoft Dynamics AX 2009 Server Configuration” application, I will cover this in another article at a later date.

Option 2: Use an existing AOS Service


Option 1: New AOS Service

1.  Create a new Active Directory Login

e.g. CONTOSO\PerfMonAosSvc


2.  Add user to ‘Performance Log Users’ group

Performance Log Users GroupThis is required so AOS Tracing can be started via the Tracing tab found within the
“Microsoft Dynamics AX 2009 Server Configuration” application.

3.  Install a new AOS specifying the new Service Account login details when prompted,     specify not to start service after the installation is completed, this ensures you can install Service Packs and Hotfixes on the new AOS service.

4.  Ensure you install any Service Packs or Hotfixes to your current environments level.  During each install specify not to start service after the installation is complete and ensure you only select to update the AOS.

5.  You may need to add ‘EXECUTE‘ permissions on any additional custom Stored Procedures that you may have in your AX Database for your new account.

6.  Start the new AOS Service and check the application event log to ensure no warnings/errors are reported.


Option 2: Changing an Existing AOS Service

If you already have an existing AOS Service you want to configure for Performance Monitoring there are different steps to complete:

1.  Create a new Active Directory Login

      e.g. CONTOSO\PerfMonAosSvc


2.  Create a SQL Server Login

USE [master]


3.  Create the Database Login



4.  Grant Database Role Permissions

EXEC sp_addrolemember N'db_ddladmin', N'CONTOSO\PerfMonAosSvc'
EXEC sp_addrolemember N'db_datawriter', N'CONTOSO\PerfMonAosSvc'
EXEC sp_addrolemember N'db_datareader', N'CONTOSO\PerfMonAosSvc'


5.  Grant Stored Procedure Permissions

TO [CONTOSO\PerfMonAosSvc]
TO [CONTOSO\PerfMonAosSvc]

Note:  You may need to add ‘EXECUTE’ permissions on any additional custom Stored Procedures that you may have in your AX Database.

6.  Add user to ‘Performance Log Users’ group
Performance Log Users Group

This is required so AOS Tracing can be started via the Tracing tab found within the “Microsoft Dynamics AX 2009 Server Configuration” application.


7.  Ensure the Service Account has Modify, Read & Execute, List folder contents, Read, Write permissions on the Application Folder

e.g. C:\Program Files\Microsoft Dynamics AX\50\Application


8.  Ensure the Service Account has Read, Write permissions on the AOS Log folder

      e.g. C:\Program Files\Microsoft Dynamics AX\50\Server\MY_NEW_AOS_02\Log

9.  Change the AOS service account user in Services to the newly created service account

10. Restart the AOS Service.


Please as always try this setup in your Test / Dev environment prior to implementing it in your Production environment to ensure you understand the setup required and that it fits your requirements.


Additional Reading:

A great 3 part series on AX Tracing from the ‘Premier Field Engineering’ Team

Run a Dynamics AX SQL statement as an API Cursor in SSMS

We all know that AX2009 uses cursors extensively – simply executing a SQL statement in SSMS doesn’t always result in the same query plan being used that an AX generated SQL statement would use.

Want to run a query in SQL Management Studio exactly how Dynamics AX 2009 runs the query e.g. as a API Cursor so you can ensure you are looking at the same query plan AX has used then run the query below.

Simply replace the red text below with all the query variables and replace the blue text with your parameters and execute the full statement and voila you can view the exact query plan AX uses to execute the statement.

TIP: If your unsure of the variables to declare in the cursor you can find them by doing a SQL Profiler Trace.

— Normal FFO Cursor

— Script taken from AX Dynamics Performance Analyzer scripts by Rod Hansen (http://code.msdn.com/dynamicsperf)

declare @p1 int
set @p1=NULL
declare @p2 int
set @p2=0
declare @p5 int

— Fast Forward(16)+Parameterized(4096)+AutoFetch(8192)+AutoClose(16384)

set @p5=16+4096+8192+16384
declare @p6 int
set @p6=8193
declare @p7 int

— Number of Rows for AutoFetch.
— This is calculated by Maximum Buffer Size (24K default) / Row Length

set @p7=4
exec sp_cursorprepexec @p1 output,@p2 output,N’@P1 nvarchar(5),@P2 nvarchar(21)‘,N’SELECT A.SALESID,A.RECID FROM SALESLINE A WHERE ((DATAAREAID=@P1) AND (SALESID>@P2))’,@p5 output,@p6 output,@p7 output,N’ceu’,N’SO-100004′
— @p2 contains cursor handle for fetch call
exec sp_cursorfetch @p2,2,1,@p7

Show SQL Plans in Plan Cache for a table name or matching partial query text

Ever wondered what queries are calling what tables or do you have a query and want to see how many times it’s been called (since last plan cache flush) and view the query plan for it.

These queries are a good to use when performance tuning indexes and should be a part of your toolbox.  You need to know what queries are using your table before you can start to plan the best indexing strategy for your table.

Note: Query#2 will only work in SQL Server Management Studio 2008 onwards.

Here is a quick and easy way to do this:


This query will show you the plan handle value you need to extract the query plan from the plan cache, it will also show you how many times the query has been executed using that plan handle.

-- Shows SQL plan handles in plan cache for a specific piece of SQL text
SELECT plan_handle, usecounts AS ExecutionCount, st.text
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE text LIKE N'%<Enter Table name or partial Query here>%'
ORDER BY usecounts DESC


Using the plan_handle value from Query#1 insert it into the where clause and this will give you XML result which you can click on to view the graphical query plan.

-- Show XML query plan ** Only works with SSMS2008 **
sys.dm_exec_query_plan(<Paste Query "plan_handle" value from previous query here>)



Query#1 Results of ‘%EVENTINBOX%’ 

Query#2 – XML result of plan_handle (0x06001100A23AD31D40031579060000000000000000000000) from highest exection count of Query#1


Query#2 – Visual Query Plan after clicking on XML result show above