Dynamics AX Caching
Dynamics AX Caching
Cache Location
Caches are used on both the client and the server. The Microsoft
Dynamics AX runtime manages the cache by removing old records when new records
are added to the cache.
Client Cache
A client-side cache can be used only by the client. The client
cache is used when a select is
executed from the client tier. If no record is found in the client cache, the
client then searches the server cache for the record. If the record isn't
located in the server cache, it's retrieved from the database. The maximum
number of records maintained in a client cache is 100 records per table for a
given company.
Server Cache
A server-side cache can be used by any connection to the server.
The server cache is used when a select is
executed on the server tier. If no record is found in the cache, it's retrieved
from the database. The maximum number of records maintained in a server cache
is 2,000 records per table for a given company.
Record Caching
Microsoft Dynamics AX database record caching is a
performance-enhancing feature that helps avoid database access when it's not
strictly necessary. Retrieving database records from memory instead of the
database significantly speeds up data access. Caching can reduce the
performance penalty for repetitively accessing the same database records.
Types of Caching
Caching is transparent to the application; however, it's important
to know how caching works to optimize its performance in Microsoft Dynamics AX.
Following are the types of caching:
- Single-record
- Set-based
Single-record caching has the
following characteristics:
- Defined at design time
- Moves records to the cache based
on the table's CacheLookup
property and the type of SELECT
statement that is used to retrieve the record
Set-based caching has the
following characteristics:
- Defined either at design time or
in X++ code
- Moves sets of records to the cache
- Implemented either through the
table's CacheLookup
property or in code by using the RecordViewCache
class
Single-Record Caching
Record caching is enabled for a table when all the following
statements are true:
- The
CacheLookup
property on the table is enabled by setting it to one of the following
values:
· notInTTS
· Found
· FoundAndEmpty
- The
table's PrimaryIndex
property is set to a unique index that exists on the table. The RecId
index does not qualify as a caching index unless you set the table's PrimaryIndex
property to this index.
- The
record buffer disableCache
method has not been called with a parameter of true.
The fields in the table's unique index make up the caching key. A
record is placed in the cache when the following criteria are met:
- The
table is cached by setting the CacheLookup
property to notInTTS, Found, or FoundAndEmpty.
- The
SELECT
statement that selects the records uses an equal operator (==) on the
caching key. The fields in the WHERE
clause of the SELECT
statement match the fields in the index referenced by the table's PrimaryIndex
property.
The table's CacheLookup property
defines how and when records are cached as shown in the following table.
CacheLookup Property Value
|
Result
|
None
|
No data
is cached or retrieved from the cache for this table.
This
property value should be used for tables that are heavily updated or where it's
unacceptable to read outdated data.
|
NotInTTS
|
All
successful caching key selects are cached.
When in
a transaction (after ttsBegin), no caches made outside the transaction are
used. When inside a transaction, the record is read once from database and
subsequently from cache. The record is select-locked when read in a
transaction, which ensures that the record cached is not updated while the
transaction is active.
A
typical example of the NotInTTS
property is the CustTable in the Microsoft Dynamics AX standard application.
It's acceptable to read outdated data from the cache outside a transaction,
but when data is used for validation or creating references, it is ensured
that the data is real-time.
|
Found
|
All
successful caching key selects are cached. All caching key selects are
returned from the cache if the record exists there. A selectforUpdate in a transaction forces
reading from the database and replaces the record in the cache.
This is
typically used for static (lookup) tables, such as Unit, where the record
usually exists.
|
FoundAndEmpty
|
All
selects on caching keys are cached, including selects that are not returning
data.
All
caching key selects are returned from caching if the record exists there, or
the record is marked as nonexistent in the cache. A selectforUpdate in a transaction forces
reading from the database and replaces the record in the cache.
An
example of FoundAndEmpty record
caching is in the Discount table in the Microsoft Dynamics AX standard
application. By default, the Discount table has no records. By using a
FoundAndEmpty cache on this table, the keys that are queried for but not
found are stored in the cache. Subsequent queries for these same
non-existent records can be answered from the cache without a round trip
to the database.
|
EntireTable
|
Creates
a set-based cache on the server. The entire table is cached as soon as at
least one record is selected from the table.
|
The Found and FoundAndEmpty caches cross transaction boundaries.
The NotInTTS cache is newly created inside a transaction. This example,
modified for the purposes of this topic, demonstrates how records are retrieved
from the cache when the table's CacheLookup property
is set to NotInTTS, and the PrimaryIndex property
is set to a unique index on the AccountNum field.
static void NotInTTSCache(Args _args)
{
CustTable custTable;
;
// The query looks for records in the cache.
// If records don't exist, the query accesses the database.
select custTable
where
custTable.AccountNum == '4000';
// The transaction
starts.
ttsbegin;
// The cache is not
used. The query accesses the database
// and records are
placed in the cache.
select custTable
where
custTable.AccountNum == '4000';
// The query uses the
database because
// the forupdate keyword is used.
select forupdate
custTable
where
custTable.AccountNum == '4000';
// The query uses the
cache and not the database.
select custTable
where
custTable.AccountNum == '4000';
// The query uses the
cache because
// the forupdate keyword
was used previously.
select forupdate
custTable
where
custTable.AccountNum == '4000';
// The transaction is
committed.
ttscommit;
// The query will use
the cache.
select custTable
where
custTable.AccountNum == '4000';
}
If the table CacheLookup property
was set to Found or FoundAndEmpty, the first select
statement inside the transaction (after the TTSBegin
statement) would retrieve the record from the cache.
Set-Based Caching
In Microsoft Dynamics AX, groups of records can be cached all at
once with set-based caching. Set-based caching can be implemented in two
ways:
- At design time, by setting the
table's CacheLookup
property to EntireTable.
- In code, by using the RecordViewCache
class.
EntireTable Cache
When you set a table's CacheLookup property
to EntireTable, all the records in the
table are placed in the cache after the first select. This type of caching
follows the rules of single record caching in which the SELECT statement WHERE clause
fields must match those of the unique index defined in the table's PrimaryIndex property.
The EntireTable cache is located on the server and is shared by
all connections to the Application Object Server (AOS). If a select is made on
the client tier to a table that is EntireTable cached, it first looks in its
own cache and then searches the server-side EntireTable cache. An
EntireTable cache is created for each table for a given company. If you have
two selects on the same table for different companies the entire table is
cached twice.
Joins that include an EntireTable cached table are only performed
against the cached copy when all tables participating in the join are
EntireTable cached. Otherwise a database join is performed.
Important
Note:
Avoid using EntireTable
caches for large tables because once the cache size reaches 128 KB the cache is
moved from memory to disk. A disk search is much slower than an in-memory
search.
Flushing the Cache
An EntireTable cache is flushed whenever an insert, update, or
delete is made to the table. At the same time, the AOS notifies other AOSs that
their caches of the same table must be flushed. After the cache is flushed, a
subsequent select on the table causes the entire table to be cached again.
Therefore, avoid caching any table that's frequently updated. Regardless of
when updates are made, EntireTable caches are flushed every 24 hours by the
AOS.
RecordViewCache Cache
Set-based caching is implemented in code by using the RecordViewCache class. You must first create a record buffer
using the nofetch
statement and then pass the record buffer to the RecordViewCache class when it's instantiated.
The cache is created on the server and is only accessible by the
process that creates the cache object. Once the cache is instantiated, all
select statements are issued against the cache, as shown in the following
static void RecordViewCache(Args _args)
{
CustTrans custTrans;
RecordViewCache
recordViewCache;
;
// Define records to
cache.
select nofetch custTrans
where custTrans.AccountNum
== '4000';
// Cache the records.
recordViewCache = new
RecordViewCache(custTrans);
// Use cache.
select firstonly
custTrans
where
custTrans.AccountNum == '4000' &&
custTrans.CurrencyCode == 'USD';
}
Due to concurrency issues, the forUpdate keyword
on the instantiating X++ SELECT
statement should only be used when all of the records in the result set will be
updated. Otherwise it's a better strategy to use select forUpdate only for
the records that are to be updated.
The RecordViewCache class is
used in a select when the select is from a table that's cached, the select
statement doesn't participate in a join and the select WHERE clause matches the WHERE clause
with which the RecordViewCache was
instantiated.
The cache created by the RecordViewCache class stores records in a
linked list. Therefore Microsoft Dynamics AX searches the cache sequentially
for records that match the search criteria. If the SELECT statement contains an ORDER BY clause,
a temporary index is placed on the cache and the runtime uses the index when
searching records.
Thank you, I needed some tips about caching in Microsoft Dynamics AX. I sometimes don't know if i should "click here or there" - typical beginner problems. Thank you for solving them. Cheers!
ReplyDelete