【问题标题】:azure service fabric reliable dictionary linq query very slowazure service fabric 可靠的字典 linq 查询非常慢
【发布时间】:2017-03-20 08:09:27
【问题描述】:

我在服务结构有状态服务中有一本可靠的字典。我有一个简单的 linq 表达式。
我正在使用 Ix-Async 包来构建异步枚举。


using (ITransaction tx = this.StateManager.CreateTransaction())  
        {  

          var result = (await customers.CreateLinqAsyncEnumerable(tx))
                .Where(x => x.Value.NameFirst != null && x.Value.NameFirst.EndsWith(n, StringComparison.InvariantCultureIgnoreCase))
                    .Select(y => y.Value);

           return await result.ToList();


        }  

数据被组织成 2 个分区,每个分区大约有 75,000 条记录。我使用 Int64 范围作为分区键。在上面的代码中,“Result.ToList()”对每个分区执行大约需要 1 分钟。另一个奇怪的事情是,实际结果是空的!在 sql server 中运行的相同 sql 返回客户名字以“c”结尾的行。但是,这不是重点。我最关心的是“ReliableDictionary”linq 查询的性能。
问候

【问题讨论】:

  • 记录有多大?你在什么硬件上运行它?您是在本地开发机器上还是在真实集群上进行测量?同一台机器上还有其他服务吗?您是否尝试过在不使用 Ix-Async 包的情况下进行枚举,看看是否有任何区别?
  • 该表是标准表,只是它有 1 个二进制列 [图片]。这是一个本地开发集群。有 16 GB 的 RAM。插入字典的速度非常快。 [每分钟大约 2000 条记录]。字典查找键也非常快。我确实使用异步枚举器枚举了全部 75,000 条记录并应用了谓词。这仍然需要大约 50 秒。
  • 如果你能帮上忙,我不建议在其中存储图片。通常,您会将图像文件的 URL 存储在 blob 存储或其他东西中。图片大概有多大?很可能它们并非一直都保存在内存中。基本上,您所做的是在枚举期间将这些图片从磁盘上拉到 RAM 中。该枚举时间是否包括对图片数据的任何其他处理?
  • 另外,如果它在本地开发机器上,两个分区共享同一个物理机器,所以实际上你是同时拉出两组 75,000 个。
  • 另外,出于好奇,sql server 有列索引。如果没有在存储为可靠字典的序列化 POCO 上定义基于属性的索引,linq 到对象查询如何快速?搜索字典的内部查询必须进行完整的集合扫描,对吗?

标签: c# performance linq-to-entities microservices azure-service-fabric


【解决方案1】:

Reliable Dictionary 会定期从内存中删除最近最少使用的值。这是为了启用

  • 可靠的大字典
  • 更高的密度:每个副本的可靠集合密度更高,每个节点的副本密度更高。

权衡的是,这会增加读取延迟:需要磁盘 IO 来检索未缓存在内存中的值。

有几个选项可以降低枚举延迟。

1) Key Filtered Enumeration:您可以将要在查询中使用的字段移入 ReliableDictionary 的 TKey(上例中的 NameFirst)。这将允许您使用采用密钥过滤器的CreateEnumerbleAsync 重载。键过滤器允许 Reliable Dictionary 避免从磁盘中检索与查询不匹配的键的值。这种方法的一个限制是 TKey(因此其中的字段)无法更新。

2) 使用通知的内存二级索引Reliable Dictionary Notifications 可用于构建任意数量的二级索引。您可以构建一个二级索引,将所有值保存在内存中,从而交换内存资源以提供更低的读取延迟。此外,由于您可以完全控制二级索引,因此您可以保持二级索引有序(例如,在您的示例中通过 NameFirst 的反向)。

我们还在考虑使 Reliable Dictionary 的内存中 TValue 扫描策略可配置。有了这个,如果读取延迟是您的优先事项,您将能够配置 Reliable Dictionary 以将所有值保留在内存中。

由于在您的场景中,枚举的大部分时间都花在了磁盘 IO 上,因此您还可以从使用 Custom Serializer 中受益,这可以减少磁盘和网络占用。

感谢您的提问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-08
    • 2018-12-06
    • 2016-07-23
    • 2016-07-26
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多