CQSchema优化——2009IBM Rational开发者大会文稿

此文章是今年IBM Rational开发者大会给出一份关于Schema优化的文档,我只翻译其中对我们开发者有益的部分,请关注

 

1、使用VB还是使用PERL语言开发

     这个问题其实很多人都有自己的偏好。IBM在这里给出的意见是跨平台只能使用PERL,这个是理所当然的。而实际很多企业应该仅适用windows端进行访问CQ,所以使用VB比PERL更好。因为PERL在windows平台中是单线程执行,效率很差,最后使用者会很痛苦。在使用web asp的时候,更需要VB,而不能使用PERL,否则将无法使用。

      启动的时候CQ会将所有HOOK一次性加载下来,所以越多的代码就会造成启动越慢,且更多的消耗内存。

      执行时,更多的HOOK也会造成长时间响应及表现缓慢的情况。

 

2、字段的Validation Hook是每个字段更新都会触发字段的验证HOOK。这个就需要进行优化了~~

     如果确定要用验证HOOK,请使用FieldInfo->ValueChangedThisSetValue()方法来判断这个字段是否被修改过。(当然这里IBM给的是一个例子,后来发现这个方法只能对SetFieldValue这样的HOOK起作用,如果想知道这个动作是否触发了字段值更改,需要用ValueChangedThisAction()方法来判断,比较麻烦)

     还有一种解决方式,可避免使用字段的验证HOOK。使用Base型动作的验证HOOK,因为BASE型动作的验证HOOK会被在每个动作验证HOOK之前调用,所以这个HOOK也可以保证每个动作都能验证对应的字段,当然相对开发也会复杂一些。

     

     Schema的开发要尽量重用代码,比如多使用全局脚本解决,同时创建Session变量会给程序及机器带来很大的消耗,应该尽量减少session的新建。

 

3、Value_Change这个HOOK要避免循环调用,就是A变了B也跟着变,而在B的Value_Change中又要改变A,这样是不允许的,会造成程序死锁。当然CQ允许多个字段对某一字段修改,比如A变化了去修改B和C的值,而B变化了也会去修改C的值,不过这样的结果是不可预测的,不能确定是A还是B对C的结果产生影响。

 

4、Email Rule和Notification HOOK

     Email Rule定制方便,实现简单,应该是绝大部分邮件的发起。而且在v7版已经采用了一次性带入客户端进行缓存,发送邮件。

     但Email Rule无法跟踪,只能够对本记录内的字段、人员进行发送,同时Email Rule多了一次性加载时间上也是很差的。

     使用Notification Hook可以在客户端进行Email触发,而且灵活性会高很多,内容、人员可由开发者定制。

    

     看一下用Perl写的Notification Hook来替代Email Rule

 Example: Send E-Mail via Notification Hook
 my $owner = $entity->GetFieldStringValue(“owner”);
 my $submitter = $entity->GetFieldStringValue(“submitter”);
 my $id = $entity->GetFieldStringValue(“id”);
 my $mailmsg= CQMailMsg::Build();
 $mailmsg->AddTo($owner);
 $mailmsg->SetSubject($submitter);
 my $subject = “Entity “. $id . “modified.”;
 $mailmsg->SetSubject($subject);
 my $body = “Description: “. $entity->GetFieldStringValue(“Description”);
 # add more to $body as needed
 $mailmsg->SetBody($body);
 $mailmsg->Deliver();

 

5、减少在执行过程中创建AdminSession的次数

     经过测试发现,AdminSession的创建会严重影响执行速度,根据使用情况不同,大概会消耗3~42s不等。而在这一过程中,Logon的时间大概会占到95%以上,即用admin登录有40s可能在logon,而只有2s才是真正执行程序的时间。

     可以使用CQ提供的DB查询功能来实现adminsession做的事,这个过程是很简短的,一般1~2s即可完成执行。

my $queryDefObj= $session->BuildQuery(“users”);
$queryDefObj->BuildField(“login_name”);
$queryDefObj->BuildField(“fullname”);
my $resultSetObj= $session->BuildResultSet($queryDefObj);
$resultSetObj->Execute();
while ($resultSetObj->MoveNext()==$CQPerlExt::CQ_SUCCESS)
push(@choices, $resultSetObj->GetColumnValue(2));

 

6、避免使用“Recalculate Choice List”即重新计算选项列表勾选项

     这个对于List字段每次点击都会去自动获取一遍,效率相对较差。不勾选的话,即首次采集后进行缓存。

     在使用过程中发现,这个缓存是有一定问题的,除非这个List跟其他字段没有关联,最好是常量列表才使用。总之此处虽然可以优化,但对于很多使用CQ的用户来说,意义不大,开发人员也应该谨慎去掉这个选择。

 

7、理智使用Reference_List

     对于Reference_List会造成查询中关联多个表,会造成查询速度缓慢。IBM工程师建议使用DB查询来缓解这个压力。

Option 1: Use Query to avoid using Reference List
my $sqlString= “select login_namefrom users where is_active<> 0”;
my $resultSetObj= $session->BuildSQLQuery($sqlString);
$resultSetObj->Execute();
while ($resultSetObj->MoveNext() == $CQPerlExt::CQ_SUCCESS)
push(@list, $resultSetObj->GetColumnValue(1));

 

Option 2: Use a Reference List of User records
my $list = $entity->GetFieldChoiceList(“Owner”);

 

     使用Reference_List在使用主键时候使用比较好,使用DB查询在使用Reference内的属性时候比较高效。

 

8、更好的使用CQ的Reference属性关系

     有些开发人员喜欢格式化,比如获取一个项目信息,再获取一个User信息,不断的使用session.GetEntity这样的东西,其实可以很简单。

     $entity->SetFieldValue("cust_name", $entity->GetFieldStringValue("project.leader.full_name"));

 

9、附件问题,很多大公司在使用CQ时候发现,附件问题是很严重的,造成CQ数据库庞大,造成Multisite三地同步缓慢。所以附件的控制是整个平台稳定的重要一个环节。下面介绍如何控制附件的大小。

     Perl脚本

sub MaxFileSize{
my $result;
use File::stat;
my $maxFileSize= 5000000; # 5MB
# Get a list of the attachment fields in this record type...
my ($AttachmentFields) = $entity->GetAttachmentFields();
for (my($AF) = 0; $AF < $AttachmentFields->Count(); $AF++){
   my ($AttachmentField) = $AttachmentFields->Item($AF);
   my($Attachments) = $AttachmentField->GetAttachments();
   my $numAttach= $Attachments->Count();
   for (my($A) = 0; $A < $ $numAttach; $A++) {
      my($Attachment) = $Attachments->Item($A);
      # File size is always 0 before a first commit
      if ($Attachment->GetFileSize() == 0){
      $filesize= -s $Attachment->GetFileName();
      if ($filesize> $maxFileSize){
   return "Cannot add attachments larger than 5MB.";
   }
}
}
}
return $result;
}

 

vb脚本:

' 其他任何动作fire时,都会触发这个动作;
' 在这里完成:限制单个附件大小为3M
  Dim fso, f, s
     needs_Validation = ""
     set session = GetSession()
     set attachFields = AttachmentFields
' 定义一个session变量,用来作为上传了附件的标志
' session.NameValue("SessionVarPIRAttach") = "否"
' session.outputdebugstring "Fix 动作的validation hook 开始: "& vbCrLf

     ' Iterate over the attachment fields on an Entity.
     ' 遍历附件类型的字段
     For Each attachField In attachFields
        set attaches = attachField.Attachments
        ' iterate over the attachment's field attachments
  ' 遍历附件字段中的所有附件
        For Each myAttach In attaches
              filename = myAttach.FileName
              filesize = myAttach.FileSize
              ' INFO " filename is " & filename
              ' File size is always 0 before a first commit
     ' when File size is 0, the file has been added during the current action,_
     ' and is still on the local drive
              If (filesize = 0) Then
                  Set fso = CreateObject("Scripting.FileSystemObject")
                  Set f = fso.GetFile(filename)
                  filesize = f.size
              End if
         ' INFO "filename is " & filename & " size is " & filesize
           If (filesize > 3000000) Then
               needs_Validation = "Error:  File " & filename & "单个文件大小请不要超过3M"
               Exit Function
            End If
        Next
     Next

 

CQ Schema还有很多可以优化之处,但并不是上面的方法都要执行,个人建议根据个人需要。对于outputdebugstring这个,尽量少,用dbwin32跟踪后尽量注释掉或者屏蔽,否则可能会造成CQ Web问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值