从插件中调用 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除了初始数据加载场景