第十七章 性能(三)

本文仅供AX从业者和爱好者讨论学习之用,由于原文版权问题请勿转载并期待您的指正.
接上文
这种方式比下面代码显示的一条条记录插入有很大的效率提升,它们达到的效果是一样的
None.gif static   void  CopySizes(Args _args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    InventSize inventSizeTo;
InBlock.gif    InventSize inventSizeFrom;
InBlock.gif    InventTable inventTable;
InBlock.gif    ;
InBlock.gif    ttsbegin;
InBlock.gif    
while select itemId from inventTable
InBlock.gif            where inventTable.ItemId 
== 'PB-Metal Shade'
InBlock.gif        join inventSizeId,description,name from inventSizeFrom
InBlock.gif            where inventSizeFrom.ItemId 
== 'PB-Plastic Shade'
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        inventSizeTo.ItemId         
=   inventTable.itemId;
InBlock.gif        inventSizeTo.InventSizeId   
=   inventSizeFrom.InventSizeId;
InBlock.gif        inventSizeTo.Description    
=   inventSizeFrom.Description;
InBlock.gif        inventSizeTo.Name           
=   inventSizeFrom.Name;
InBlock.gif        inventSizeTo.insert();
ExpandedSubBlockEnd.gif    }

InBlock.gif    ttscommit;
InBlock.gif 
ExpandedBlockEnd.gif}
如果要拷贝10个大小,这种场景下select语句会跟数据库服务器发生一次交互,insert语句会发生10交互,总共11次交互.
但是批操作可能会被降级成记录操作(译注:原文是record-base operation,直接翻译是基于记录的操作,感觉有些别扭,这里翻译成记录操作).在满足下面任何一种情况时都会发生降级:
1.该表是全表缓存的.
2.目标表的(译注:即要在其中插入记录的表)insert或者aosValidateInsert方法被重载.
3.设置了在目的表中插入记录时产生预警.
4.配置了数据库日志以记录目的表的插入动作
(译注:AX可以通过  系统管理->设置->数据库日志  设置记录某些表的插入或者更改动作,如果在这里设置了,那么在设定了的表发生插入或者更改动作时,AX运行时会把这些信息记录在表SysDataBaseLog中,可以通过 系统管理->查询->数据库日志 查看)
DynamicsAX应用运行时会自动处理降级,内部执行的过程跟前面提到的while select一样.
重要   当DynamicsAX应用运行时检测重载方法时,它只关心这些方法是否实现.它不关心这些被重载的方法是否只包含默认的X++代码.因此,即使一个方法只包含如下X++代码,应用运行时也会认为它被重载了:
None.gifpublic void  insert()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
{
InBlock.gif    super();
ExpandedBlockEnd.gif}
这样任何批插入操作就被降级了.因此删除这样的方法以避免效率的降低(译注:原文It is important that you delete such a method to avoid the downgrade with its performance ramifications其中ramification是分支,分歧或者后果的意思,结合原文翻译成这几个意思感觉都不太好理解,这里省略了).
但是除了表采用了全局缓存外,可以避免上面提到的功能引起的任何降级.  记录缓存(译注:原文The record buffer,这个还真不知道怎么翻译,实际上就是表变量,还真整不明白为什么叫buffer) 包含一些方法,这些方法可以关掉运行时执行的决定是否应该将insert_recordset降级的检测.调用skipDataMethods(true)阻止insert是否被重载的检测,调用skipAosValidation(true)阻止检测aosValidateInsert方法.调用skipDatabaseLog(true)阻止检测是否配置了数据库日志来记录该表的插入操作,调用skipEnvents(true)阻止检测是否在该表上设定了由插入事件触发的预警.下面的X++代码包含了对skipDataMethods(true)的调用,因此可以确保insert_recordset不会因为InventSize的insert方法被重载而引起的降级
None.gif static   void  CopySizes(Args _args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    InventSize  inventSizeTo;
InBlock.gif    InventSize  inventSizeFrom;
InBlock.gif    InventTable inventTable;
InBlock.gif    ;
InBlock.gif    ttsbegin;
InBlock.gif    inventSizeTo.skipDataMethods(
true);
InBlock.gif    insert_recordset inventSizeTo(ItemId,InventSizeId,Description,Name)
InBlock.gif        select itemId from inventTable
InBlock.gif            where inventTable.ItemId 
== 'PB-Metal Shade'
InBlock.gif        join inventSizeId,description,name from inventSizeFrom
InBlock.gif            where inventTable.ItemId 
== 'PB-Plastic Shade';
InBlock.gif    ttscommit;
InBlock.gif
ExpandedBlockEnd.gif}
Skip方法在使用的时候必须特别注意,  避免在Insert中实现X++代码因为将不会被执行,不会被触发的事件,不会被创建的日志,等等。如果重载了insert方法,应该使用交叉应用系统看是否有X++代码调用了skipDataMethods(true),否则X++代码可能会不执行insert方法.另外,当调用skipDataMethods(true)时,确保不执行重载的insert方法中的X++代码不会引起数据的不一致.
注意skip方法只是用来影响insert_recordset操作是否降级。比如调用skipDataMethods(true)来阻止因为重载了insert方法而引起的降级,如果最终操作被降级了,insert的重载版本仍然会被执行。操作会被降级,比如,如果配置了数据库日志来记录表的插入记录。在前面的例子中,如果配置了数据库日志记录表InventSize的插入操作表InventSize的重载版本的insert方法将会被调用,因为insert_recordSet操作会被转换成while select,在这种情况下重载版本的insert方法会被调用。
update_recordset 操作符
update _recordset操作符与 insert_recordset操作符的表现类似。下面的X++代码证明了这一点,该语句将一个产品的所有尺寸用一个新的描述信息更新.
None.gif static   void  UpdateSizes(Args _args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    InventSize inventSize;
InBlock.gif    ;
InBlock.gif    ttsbegin;
InBlock.gif    update_recordset inventSize
InBlock.gif        setting Description 
= 'This Size for item PB-Metal Shade'
InBlock.gif        where inventSize.ItemId 
== 'PB-Metal Shade';
InBlock.gif    ttscommit;
InBlock.gif
ExpandedBlockEnd.gif}
update_recordset 操作的执行将提交给数据库服务器一条语句,在SQL Server2000中这条语句的语法类似于UPDATE <table><SET><field and expression list> WHERE <preedicates>.与Insert_recordSe一样,该操作比起记录级操作需要一条条单独更新效率有了很大的提升。下面的X++代码展示了记录级操作,它所实现的功能跟前面的例子是一样的。这段代码首先选出所有满足条件的记录,设定新的描述信息,最后更新记录。
None.gif static   void  UpdateSizes(Args _args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    InventSize inventSize;
InBlock.gif    ;
InBlock.gif    ttsbegin;
InBlock.gif    
while select forupdate inventSize
InBlock.gif        where inventSize.ItemId 
== 'PB-Metal Shade'
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            inventSIze.Description 
= 'This size is for item PB-Metal Shade';
InBlock.gif            inventSize.update();
ExpandedSubBlockEnd.gif        }

InBlock.gif    ttscommit;
InBlock.gif
ExpandedBlockEnd.gif}
如果有10条记录满足条件,那么一条select语句和10条更新语句将会提交给数据库服务器,而update_recordSet只需要一条update语句。
如果特定的方法被重载或者DynamicsAX应用的设定,update_recordset操作也会被降级。满足如下条件中的一个就会引起降级:
1.表应用了全表缓存。
2.目的表的update,aosValidateUpdate或者aosValidateRead方法被重载。
3.在目的表上设定有由更新查询出发的预警规则。
4.在数据库日志中配置了记录目的表的更新查询。
DynamicsAX运行时会自动处理降级,在内部的执行情况跟前面举的例子中的while select 一样。
(译注:我测试的结果是作者举的例子中update_recordset并不能成功降级成while select语句完成更新,具体描述请参照 本文)。
前面功能应起的降级是可以避免的,除非采用了全表缓存.记录缓存(译注:表变量)包含关闭检测的方法,这些检测由应用运行时执行的用于决定update_recordset操作是否应该被降级的.调用skipDataMethod(true)阻止检测update是否被重载,调用skipAosValidation(true)阻止检测aosValidateUpdate和aosValidateRead方法。调用skipDatabaseLog(true)阻止检测数据库日志是否配置用来记录该表的更新操作,调用skipEvents(true)阻止检测是否在该表上配置了由更新事件触发的预警。
正如前面提到的那样,在结合update_recordset是用skip方法的时候要特别小心并采取相应的预防措施。同样,skip方法只会影响update_recordset操作是否降级成while select,如果操作最终降级了,数据库日志,预警和被重载方法的执行都会发生,尽管各自的skip方法被调用。
技巧:如果update_recordset操作被降级成while select ,select语句使用在表上指定的并发模型。可以在update_recordset语句上应用optimisticlock和pessimisticlock来强制被降级后的操作采用指定的并发模型。
delete_from操作符
delete_from与insert_recordset和update_recordset操作符类似,可以向数据库提交一个条语句完成多条记录的删除。下面的X++代码删除了一个产品的所有的尺寸。
None.gif static   void  DeleteSizes(Args _args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    InventSize inventSize;
InBlock.gif    ;
InBlock.gif    ttsbegin;
InBlock.gif        delete_from inventSize
InBlock.gif            where inventSize.ItemId 
== 'PB-Metal Shade';
InBlock.gif    ttscommit;
InBlock.gif 
ExpandedBlockEnd.gif}

这段代码提交给SQL Server2000语法类似于DELETE <table> WHERE <predicates>,执行的结果跟通过如下X++代码逐条删除一样。

None.gif static   void  DeleteSizes(Args _args)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    InventSize inventSize;
InBlock.gif    ;
InBlock.gif    ttsbegin;
InBlock.gif    
while select forupdate inventSize
InBlock.gif        where inventSize.ItemId 
== 'PB-Metal Shade'
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        inventSize.delete();
ExpandedSubBlockEnd.gif    }

InBlock.gif    ttscommit;
ExpandedBlockEnd.gif}

同样,由于只向数据库提交一条语句,比起逐条删除使用delete_from有很大的效率提升。
与insert_recordset和update_recordset类似,delete_from会因为类似的原因降级。如果满足如下条件中的一个则会发生降级:
1.表是全表缓存的;
2.目的表的delete,aosValidateDelete或者aosValidateRead方法被重载;
3.在目的表上配置了由删除触发的预警;
4.配置了数据库日志用于记录目的表的删除操作。
如果在表上定义了delete actions也会发生降级。DynamicsAX应用运行时会自动处理降级在内部执行与前面提到的while select 同样的操作。
可以避免由前面提到的功能引起的降级,除非采用了全表缓存。记录缓存(译注:表变量)包含关闭检测的方法,这些检测由应用运行时执行的用于决定delete_from操作是否应该被降级的.调用skipDataMethod(true)阻止检测update是否被重载,调用skipAosValidation(true)阻止检测aosValidateDelete和aosValidateRead方法。调用skipDatabaseLog(true)阻止检测数据库日志是否配置用来记录该表的删除操作,调用skipEvents(true)阻止检测是否在该表上配置了由删除事件触发的预警。调用skipDeleteActions(true)阻止检测是否在目的表的元数据上定义了delete actions。
正如前面提到的skip方法使用的描述,在降级发生的时候,对应的行为并不会被跳过(译注:原文可能是为了避免重复的语句太多换了个说法,作者想表达的意思跟前面是一样的),delete_from也可以使用update_recordset使用的并发模型。
注释:记录缓存(译注:表变量)也包含skipDeleteMethod方法。调用该方法跟调用skipDataMethods(true)方法的效果是一样的。它实际上触发了同样的DynamicsAX应用运行时逻辑,所以可以结合insert_recordset和update_recordset使用skipDeleteMethod方法,尽管这并不会提高X++代码的可读性(译注:那何必要加这么个方法那?)

转载于:https://www.cnblogs.com/Farseer1215/archive/2007/05/08/731578.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值