从插件中调用 ExecuteMultipleRequest 有用吗?
Is It Beneficial To Call ExecuteMultipleRequest From Within A Plugin?
我知道 ExecuteMultipleRequest 在从 CRM 外部执行批量更新时是一个巨大的性能助推器。我不知道从 CRM 插件中调用它是否有益。
我目前的理解是,使用 ExecuteMultipleRequest 的主要性能提升在于实际的 SOAP 消息传递成本。因此(为了更新 5000 条记录)而不是发送 5000 条单独的 Soap 消息(每条都必须进行序列化、验证、传输等),所有这些消息都必须发送到服务器,您可以只发送一条包含 5000 条记录的消息。但是当从插件调用时,您已经在服务器上,因此不必进行 SOAP 调用,因此使用它没有任何好处。
还有其他一些我没有看到的潜在好处吗?
所以我做了我之前应该做的,只是创建了一个插件来测试这个。这是我本地 VM 上的 CRM 2013(预操作)运行,因此结果可能会有所不同,但我看到普通的旧 Create 每 100 个实体减少了大约 290 毫秒
我第一次创建这个插件
public class ExecuteMultipleTester : PluginBase
{
protected override void ExecuteInternal(Common.Plugin.LocalPluginContext pluginContext)
{
var watch = new Stopwatch();
var service = pluginContext.OrganizationService;
watch.Start();
var request = new ExecuteMultipleRequest
{
Settings = new ExecuteMultipleSettings
{
ContinueOnError = false,
ReturnResponses = false,
},
Requests = new OrganizationRequestCollection()
};
for (var i = 0; i < 100; i++)
{
request.Requests.Add(new CreateRequest
{
Target = new new_Year
{
new_Year = i + "- B",
new_YearIntValue = i,
}
});
}
service.Execute(request);
watch.Stop();
var multipleCreate = watch.ElapsedMilliseconds;
watch.Restart();
for(var i = 0; i < 100; i++)
{
service.Create(new new_Year
{
new_Year = i + "- A",
new_YearIntValue = i,
});
}
watch.Stop();
throw new InvalidPluginExecutionException(String.Format("ExecuteMultipleRequest Time was: {0}ms, Standard was: {1}ms", multipleCreate, watch.ElapsedMilliseconds));
}
}
注册插件和运行 10 次测试。以下是结果(ASCII 表,哦耶!):
+------------------+---------------+-------+
| Execute Multiple | Sevice.Create | Diff |
+------------------+---------------+-------+
| 777 | 408 | 369 |
| 493 | 327 | 166 |
| 614 | 346 | 268 |
| 548 | 331 | 217 |
| 577 | 312 | 265 |
| 675 | 313 | 362 |
| 574 | 318 | 256 |
| 553 | 326 | 227 |
| 810 | 318 | 492 |
| 595 | 311 | 284 |
+------------------+---------------+-------+
| Average Diff: | 290.6 |
+------------------+---------------+-------+
因此,根据这些结果,无需从插件中执行 ExecuteMultipleRequest。您已经在服务器上,必须执行更多代码才能执行相同的操作。
更新 1 - 1000 针对完整环境创建测试
我 运行 再次测试创建 1000 条记录,并在一个完整的环境中使用 SQL、服务和 Web 的单独框。结果非常相似(只有 运行 5 次测试,因为它花费了更长的时间)
+------------------+----------+--------+
| Execute Multiple | Standard | Diff |
+------------------+----------+--------+
| 18922 | 15057 | 3865 |
| 18668 | 14946 | 3722 |
| 18162 | 14773 | 3389 |
| 19059 | 14925 | 4134 |
| 18334 | 15306 | 3028 |
+------------------+----------+--------+
| | Average | 3627.6 |
+------------------+----------+--------+
有趣的是,记录多 10 倍,时间长约 25 倍,但差异仅多 12 倍。 (尝试进行更新而不是删除,但我不断收到超时错误,即使每次只有一个错误...一定是在创建某种无限循环,只是不确定是什么...)
对于 1000 个创建,它慢了将近 4 秒。我不会在我的插件中使用它...
这些类型的结果与我在 运行ning 测试一个一体机(即 CRM 服务器,SQL,......全部包含在一个盒子中)时看到的结果一致机器)。当 运行 针对更传统的部署时,我看到这些结果相反。此外,随着更多消息被添加到您的请求中,差距会显着扩大。考虑增加循环以处理 300、500 或 1000(ExecuteMultipleRequest 的默认最大值)记录,并针对已将 CRM 前端、CRM 异步和 SQL 服务器分开的部署 运行不同的盒子。
我知道这是一个古老的问题/答案,但自从我在研究中发现它后,我想我也应该补充一下我在 MSDN 上找到的一些信息:
Throttling of concurrent calls – for Microsoft Dynamics 365 (online)
there is a limit of 2 concurrent ExecuteMultipleRequest executions per
organization. If that limit is exceeded, a Server Busy
fault is
thrown before the first request is ever executed. For an on-premises
deployment, throttling is not enabled by default.
https://msdn.microsoft.com/en-au/library/jj863631.aspx#limitations
基于此,我建议在任何情况下都不要使用 ExecuteMultipleRequest
除了初始数据加载场景
我知道 ExecuteMultipleRequest 在从 CRM 外部执行批量更新时是一个巨大的性能助推器。我不知道从 CRM 插件中调用它是否有益。
我目前的理解是,使用 ExecuteMultipleRequest 的主要性能提升在于实际的 SOAP 消息传递成本。因此(为了更新 5000 条记录)而不是发送 5000 条单独的 Soap 消息(每条都必须进行序列化、验证、传输等),所有这些消息都必须发送到服务器,您可以只发送一条包含 5000 条记录的消息。但是当从插件调用时,您已经在服务器上,因此不必进行 SOAP 调用,因此使用它没有任何好处。
还有其他一些我没有看到的潜在好处吗?
所以我做了我之前应该做的,只是创建了一个插件来测试这个。这是我本地 VM 上的 CRM 2013(预操作)运行,因此结果可能会有所不同,但我看到普通的旧 Create 每 100 个实体减少了大约 290 毫秒
我第一次创建这个插件
public class ExecuteMultipleTester : PluginBase
{
protected override void ExecuteInternal(Common.Plugin.LocalPluginContext pluginContext)
{
var watch = new Stopwatch();
var service = pluginContext.OrganizationService;
watch.Start();
var request = new ExecuteMultipleRequest
{
Settings = new ExecuteMultipleSettings
{
ContinueOnError = false,
ReturnResponses = false,
},
Requests = new OrganizationRequestCollection()
};
for (var i = 0; i < 100; i++)
{
request.Requests.Add(new CreateRequest
{
Target = new new_Year
{
new_Year = i + "- B",
new_YearIntValue = i,
}
});
}
service.Execute(request);
watch.Stop();
var multipleCreate = watch.ElapsedMilliseconds;
watch.Restart();
for(var i = 0; i < 100; i++)
{
service.Create(new new_Year
{
new_Year = i + "- A",
new_YearIntValue = i,
});
}
watch.Stop();
throw new InvalidPluginExecutionException(String.Format("ExecuteMultipleRequest Time was: {0}ms, Standard was: {1}ms", multipleCreate, watch.ElapsedMilliseconds));
}
}
注册插件和运行 10 次测试。以下是结果(ASCII 表,哦耶!):
+------------------+---------------+-------+
| Execute Multiple | Sevice.Create | Diff |
+------------------+---------------+-------+
| 777 | 408 | 369 |
| 493 | 327 | 166 |
| 614 | 346 | 268 |
| 548 | 331 | 217 |
| 577 | 312 | 265 |
| 675 | 313 | 362 |
| 574 | 318 | 256 |
| 553 | 326 | 227 |
| 810 | 318 | 492 |
| 595 | 311 | 284 |
+------------------+---------------+-------+
| Average Diff: | 290.6 |
+------------------+---------------+-------+
因此,根据这些结果,无需从插件中执行 ExecuteMultipleRequest。您已经在服务器上,必须执行更多代码才能执行相同的操作。
更新 1 - 1000 针对完整环境创建测试
我 运行 再次测试创建 1000 条记录,并在一个完整的环境中使用 SQL、服务和 Web 的单独框。结果非常相似(只有 运行 5 次测试,因为它花费了更长的时间)
+------------------+----------+--------+
| Execute Multiple | Standard | Diff |
+------------------+----------+--------+
| 18922 | 15057 | 3865 |
| 18668 | 14946 | 3722 |
| 18162 | 14773 | 3389 |
| 19059 | 14925 | 4134 |
| 18334 | 15306 | 3028 |
+------------------+----------+--------+
| | Average | 3627.6 |
+------------------+----------+--------+
有趣的是,记录多 10 倍,时间长约 25 倍,但差异仅多 12 倍。 (尝试进行更新而不是删除,但我不断收到超时错误,即使每次只有一个错误...一定是在创建某种无限循环,只是不确定是什么...)
对于 1000 个创建,它慢了将近 4 秒。我不会在我的插件中使用它...
这些类型的结果与我在 运行ning 测试一个一体机(即 CRM 服务器,SQL,......全部包含在一个盒子中)时看到的结果一致机器)。当 运行 针对更传统的部署时,我看到这些结果相反。此外,随着更多消息被添加到您的请求中,差距会显着扩大。考虑增加循环以处理 300、500 或 1000(ExecuteMultipleRequest 的默认最大值)记录,并针对已将 CRM 前端、CRM 异步和 SQL 服务器分开的部署 运行不同的盒子。
我知道这是一个古老的问题/答案,但自从我在研究中发现它后,我想我也应该补充一下我在 MSDN 上找到的一些信息:
Throttling of concurrent calls – for Microsoft Dynamics 365 (online) there is a limit of 2 concurrent ExecuteMultipleRequest executions per organization. If that limit is exceeded, a
Server Busy
fault is thrown before the first request is ever executed. For an on-premises deployment, throttling is not enabled by default.
https://msdn.microsoft.com/en-au/library/jj863631.aspx#limitations
基于此,我建议在任何情况下都不要使用 ExecuteMultipleRequest
除了初始数据加载场景