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 code (from Inside Dynamics AX 4.0, Chapter 17, page 450).
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.
The EntireTable Cache
In addition to the three caching methods described so far, a fourth caching option can be set on a table. This option is the EntireTable, which enables a set-based cache. The option causes the AOS to mirror the table in the database by selecting all records in the table and inserting them into a temporary table when any record from the table is selected for the first time. The first process to read from the table could therefore experience a longer response time because the application runtime reads all records from the database. Subsequent select queries then read from the entire-table cache instead of from the database.
A temporary table is usually local to the process that uses it, but the entire-table cache is shared among all processes that access the same AOS. Each company (as defined by the DataAreaId field) has an entire-table cache, so two processes requesting records from the same table from different companies use different caches, and both could experience a longer response time to instantiate the entire-table cache.
The entire-table cache is a server-side cache only. When requesting records from the client tier on a table that is entire-table cached, the table behaves as a Found cached table. If a request for a record is made on the client tier that qualifies for searching the record cache, the client first searches the local Found cache. If the record is not found, the client calls the AOS to search the entire-table cache. When the application runtime returns the record to the client tier, it inserts the record into the client-side Found cache.
The entire-table cache is not used when executing a select statement by which an entire-table-cached table is joined to a table that is not entire-table cached. In this situation, the entire select statement is parsed to the database. However, when select statements are made that access only the single entire-table cached table, or when joining other entire-table cached tables, the entire-table cache is used.
The Dynamics AX application runtime flushes the entire-table cache when records are inserted, updated, or deleted in the table. The next process, which selects records from the table, suffers a degradation in performance because it must re-read the entire table into cache. In addition to flushing its own cache, the AOS that executes the insert, update, or delete also informs other AOSs in the same installation that they must flush their caches on the same table. This prevents old and invalid data from being cached for too long in the entire Dynamics AX application environment. In addition to this flushing mechanism, the AOS flushes all the entire-table caches every 24 hours.
Because of the flushing that results when modifying records in a table that has been entire-table cached, you should avoid setting up entire-table caches on frequently updated tables. Rereading all records into the cache results in a performance loss, which could outweigh the performance gain achieved by caching records on the server tier and avoiding round trips to the database tier. The entire-table cache setting on a specific table can therefore be overwritten at run time when you configure the Dynamics AX application.
Even if the records in a table are fairly static, you might achieve better performance by not using the entire-table cache if the number of records in the table is large. Because the entire-table cache uses temporary tables, it changes from an in-memory structure to a file-based structure when the table uses more than 128 kilobytes (KB) of memory. This results in performance degradation during record searches. The database search engines have also evolved over time and are faster than the ones implemented in the Dynamics AX application runtime. It might be faster to let the database search for the records than to set up and use an entire-table cache, even though a database search involves round trips to the database tier.
For PriceDiscTable included Trade Agreement information. When you create a Sales/Purchase line, it become very slow when your pricedisctable has 30000 records because the table's cache (cache lookup) type is entiretable. It is possible to change cache type to Found.