为了加快对AX表纪录的访问,可以把从数据库读取的纪录缓存在内存中,以减少对数据库的频繁读取提高性能。纪录缓存有两种,一是单条纪录缓存,二是集合缓存。
集合缓存可以在设计时将表的的CacheLookup属性设为EntireTable来实现,全表缓存在服务器端,为所有连接共享,客户端在访问表时先查找自己的缓存,再到服务器上查找全表缓存。全表缓冲是分公司创建的,如果SELECT操作来自于不同公司,服务器会为每个公司创建一个单独的缓冲。对表做insert、update和delete操作时,会自动清理表的全表缓存,也会自动通知其他服务器端清理相应表的缓存,对表重新读取时生成新的全表缓存,因此不要对太多纪录的表做全表缓存,和内存临时表类似,如果缓冲区大小超过128KB,数据会被移动到硬盘,这也会影响到缓存的性能。即使表没有更新,AOS也会每24小时清空一次全表缓存。
集合缓存也可以通过代码实现:
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'; }
上面的代码使用RecordViewCache对从custTrans选择出来的纪录做了缓存,注意在将表变量传递给RecordViewCache前,相应的SELECT语句使用了nofetch关键字。缓冲区也是在服务器端创建,但只能被创建缓冲区的进程使用。后续的第二个SELECT就是从缓冲区读取数据,注意后一个SELECT的WHERE限定范围要在第一个SELECT的WHERE范围内,因此如果要对纪录使用ForUpdate select操作,最后是更新选择出来的所有纪录。
单纪录缓存在把表属性CacheLookup设置为NotInTTS,或者Found,又或者FoundAndEmpty且表变量的disableCache没有使用true参数调用时启用,纪录根据Unique索引缓存,后续select语句使用unique索引WHERE ==查询时从缓冲中取出纪录。单纪录缓存区在客户端和服务器端都有保存,客户端缓存只能被客户端使用,如果客户端没有找到纪录,则到服务器端查找,如果服务器端缓冲区也没有,则从数据库读取出,客户端缓冲区保存的纪录数可以在System administration/Setup/System/Server configuration/Performance optimization>Client record cache factor设置。服务器端的缓冲区可以被多个连接共享,服务器缓冲区可缓冲纪录数及缓冲区大小在前面配置的Server configuration/Cache Limits配置。
表属性CacheLookup有几个取值,它们之间有所区别:NotInTTS,表示在使用ttsbegin开始一个事务之后,表纪录被SELECT锁定,表第一次从数据库,后续的访问则作用于缓冲区,注意事务之外创建的缓冲区不被使用;Found,只要在缓冲区有相应的缓冲键值纪录都可以使用,包括在事务中,除了在事务中使用select forupdate,这会强制从数据库读取数据代替缓冲区中的纪录;FoundAndEmpty,和Found不同的地方在于如果SELECT没有从数据库读取到纪录,相应的纪录也会在缓冲区创建,这些纪录被标记为不存在,后续再次查找这些不存在的纪录也不会再到数据库读取而是从缓冲区就能直接得到答案返回;EntireTable,整表缓存已经讲过了。
除了上面的表缓存外,还可以使用SystemGlobalObjectCache缓存机制,它在服务器端创建缓冲区为所有client连接共享,注意和SysGlobalCache的区别,后者是面向某个客户会话的,它的使用参见http://msdn.microsoft.com/en-us/library/hh608239.aspx。
更多有关表缓存的内存见http://msdn.microsoft.com/en-us/library/bb278240.aspx。