在Dynamics 365客户参与中检索审核数据的性能问题

时间:2019-07-18 18:44:41

标签: c# dynamics-crm microsoft-dynamics

我们有一个从Dynamics 365客户参与中检索审核数据的解决方案。自2019年3月以来,我们在检索审核数据时遇到了一些性能问题,超时或错误消息。有关异常消息的详细信息,请参见帖子结尾。

我们正在使用RetrieveMultipleRequest并获取XML以检索审核数据。请参阅帖子结尾以获取XML。第一次运行仅具有le条件(小于当前时间戳),随后的运行将具有gt和le约6小时的时间范围。

我们以前的批量大小为500,审核检索很好。现在,即使只有200条记录,我们也得到TimeoutException(现在有10分钟的超时时间)或ObjectDisposedException(有关完整堆栈,请参见发布结束),即使对于少量记录(例如,一个实体的236条审核记录的批处理大小为200) )。

在某些情况下,我们在Dynamics env客户中,批次大小从50到400的检索速度约为每秒0.7记录。此处的性能非常差。

基于前提条件的CRM,这是“审核”表结构:

CREATE TABLE [dbo].[AuditBase](
   [AttributeMask] [nvarchar](max) NULL,
   [TransactionId] [uniqueidentifier] NOT NULL,
   [Action] [int] NULL,
   [ObjectId] [uniqueidentifier] NOT NULL,
   [ObjectIdName] [nvarchar](1) NULL,
   [UserId] [uniqueidentifier] NOT NULL,
   [ChangeData] [nvarchar](max) NULL,
   [CreatedOn] [datetime] NOT NULL,
   [Operation] [int] NOT NULL,
   [AuditId] [uniqueidentifier] NOT NULL,
   [CallingUserId] [uniqueidentifier] NULL,
   [ObjectTypeCode] [int] NULL,
   [RegardingObjectId] [uniqueidentifier] NULL,
   [RegardingObjectIdName] [nvarchar](4000) NULL,
   [UserAdditionalInfo] [nvarchar](400) NULL
)
GO
ALTER TABLE [dbo].[AuditBase] ADD  DEFAULT (newsequentialid()) FOR [AuditId]

请注意,根本没有密钥,所有实体的审核数据将存储在同一表中。另外,我们正在检索具有某些gt和le条件的记录,CRM备份也将通过“ CreatedOn”对记录进行排序吗?使用排序,尽管我不确定它在内部排序的数据量,但检索肯定会很慢。

任何人都可以对此有所了解吗?


获取XML:

    <fetch no-lock='true'>
    <entity name='audit'>
        <filter type='and' >
            <condition attribute='operation' operator='in' >
                <value>2</value>
                <value>3</value>
            </condition>
            <condition attribute='action' operator='not-in' >
                <value>14</value>
                <value>15</value>
                <value>48</value>
                <value>49</value>
                <value>53</value>
                <value>54</value>
                <value>55</value>
                <value>56</value>
                <value>57</value>
                <value>58</value>
                <value>59</value>
                <value>60</value>
                <value>62</value>
                <value>63</value>
                <value>64</value>
                <value>65</value>
                <value>100</value>
                <value>101</value>
                <value>102</value>
                <value>103</value>
                <value>104</value>
                <value>105</value>
                <value>106</value>
                <value>107</value>
                <value>108</value>
                <value>109</value>
                <value>110</value>
                <value>111</value>
                <value>112</value>
                <value>113</value>
            </condition>
            <condition attribute='objecttypecode' operator='eq' value='1' />
            <condition attribute='createdon' operator='gt' value='2019-06-18T10:01:13.8571635Z' />
            <condition attribute='createdon' operator='le' value='2019-06-18T16:00:53.9247159Z' />
        </filter>
    </entity>
</fetch>

例外1:

    System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.ServiceModel.Security.TransportSecurityProtocol'.
Server stack trace: 
at System.ServiceModel.Channels.CommunicationObject.ThrowIfClosedOrNotOpen()
at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout)
at System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]: 
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at Microsoft.Xrm.Sdk.IOrganizationService.Execute(OrganizationRequest request)

例外2:

    System.TimeoutException: The request channel timed out while waiting for a reply after 00:09:59.9990005. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'https://xxx.dynamics.com/XRMServices/2011/Organization.svc' has exceeded the allotted timeout of 00:10:00. The time allotted to this operation may have been a portion of a longer timeout. ---> System.Net.WebException: The operation has timed out
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   --- End of inner exception stack trace ---
Server stack trace: 
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Microsoft.Xrm.Sdk.IOrganizationService.Execute(OrganizationRequest request)
   at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.ExecuteCore(OrganizationRequest request)
   at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.Execute(OrganizationRequest request)

1 个答案:

答案 0 :(得分:2)

该FetchXML中的条件数量可能是导致此问题的原因。 我的想法是:

  1. 查看是否可以寻求Microsoft支持来帮助您为该特定查询的ObjectTypeCode,Operation,Action和CreatedOn或“覆盖索引”添加custom indexes

  2. 大大缩小条件的范围-仅在ObjectTypeCode和CreatedOn条件下查看其性能。然后在内存中执行其他过滤。是的,您将检索更多的记录,但是增加RAM中筛选的速度可能是值得的。

  3. 您可能还想尝试仅检索某些列而不是整个实体。一种方法是在第一次通过时仅检索进行筛选所需的列,并通过页面进行分页以获得所需的实际记录的ID。然后也许翻阅ID,并一次发出包含50个ID的Fetch来检索这些记录的其余列。

  4. 为了使审核数据集尽可能小,如果您有任何更新帐户记录的流程或应用,请确保它们仅更新必要的列。如果审核历史记录显示大量未更改的数据被推回到相同的字段中,则您可以更新代码以减少正在更新的字段。

  5. 也许考虑将审计数据导出到SQL的选项。