【问题标题】:How to approach multiple parsing of large amount of data (800k records)?如何处理大量数据(80 万条记录)的多次解析?
【发布时间】:2017-11-16 15:13:23
【问题描述】:

我有一个验证某些 CSV 文件的桌面应用程序。 我得到了这个 CSV 文件,我需要根据多个业务规则对其进行解析和验证。这些业务规则可以特别适用于每条记录,或者它们可以检查具有与文件中所有记录相关的范围的集成债券。该文件有将近 80 万条记录。

这是我目前解决问题的方法:

  1. 我上传了 csv 文件并将每一行转换为一个自定义对象(这里使用了一个 for 循环),我最终将其存储在一个列表中。这一点通常需要 3 到 6 秒,所以我不认为这是一个问题。
  2. 我将列表传递给验证器类,这要归功于 StructureMap 将所有业务规则作为单独的类。
  3. 我遍历业务规则。我的第一个业务规则抛出了这样的异常:

CLR 在 60 秒内无法从 COM 上下文 0xa4234fc8 转换到 COM 上下文 0xa42350f0。拥有目标上下文/单元的线程很可能要么进行非泵送等待,要么处理非常长时间运行的操作而不泵送 Windows 消息。这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随着时间的推移不断累积。为避免此问题,所有单线程单元 (STA) 线程都应使用泵送等待原语(例如 CoWaitForMultipleHandles)并在长时间运行的操作期间定期泵送消息。

我知道这可以隐藏,但我不想隐藏错误,我想了解我可以做些什么来使代码更有效率。我已经消除了代码中所有抛出的异常,它确实工作得更好。

对于每条记录,我在业务规则中运行以下代码:

var mandatoryFields = GetFieldsWithAttribute<MandaroryFieldAttribute>(package);

foreach (var field in mandatoryFields)
{
    var fieldValue = field.GetValue(package, null).ToString();

    if (!string.IsNullOrWhiteSpace(fieldValue))
        continue;

    var errorMessage = GetErrorMessage(package.RowNumber, field.Name,
        field.GetAttributeForPackage<CsvFieldNameAttribute>().Name);

    if (FailedResults.Contains(errorMessage))
        continue;

    FailedResults.Add(errorMessage);
}

由于有很多字段 - 我决定使用自定义属性验证字段,以使流程更加通用。 System.Reflection 用于两个扩展方法中:GetAttributeForPackage 和 GetFieldsWithAttribute。

  1. 将总结验证的报告写入文本文件。

在我看来,问题是我必须解析每条记录,对于某些规则,对于一个规则的所有记录。

我没有解析大量数据的经验。任何人都可以就如何处理这个问题提出建议吗?

【问题讨论】:

  • 为什么不逐行或成串读取文件,比如说 1.000 行?
  • @RomanoZumbé 因为“业务规则......可以检查具有与文件中所有记录相关的范围的集成债券”
  • 如果将它们存储在列表中,则最多可以处理 N 条记录。墨菲定律要求您迟早会得到一个包含 N+1 条记录的 CSV 文件。 SO 的赔率是 100%。项目 > 属性 > 构建选项卡,取消选中“首选 32 位”复选框。你不喜欢它。
  • 你能找出一个引发错误的规则吗?
  • 只要问题是抽象的,您就会得到“抽象”的答案。尝试改变你处理它的方式:1)不要将所有数据保存在内存中,索引它或使用易于索引的中间格式(例如数据库),2)如果你可以加载所有数据,那么也许你只需要使用更少的内存贪婪验证。详细信息很重要,您还没有提供。

标签: c# .net large-data


【解决方案1】:

有几件事可以帮助你:

  • 由于您的文件很大,我建议您使用Memory-mapped files .这使程序员能够处理非常大的文件

    由于您有很多记录需要验证,您可以考虑使用 线程或并行编程(任务)。这样执行将 更快。

    我猜你正在使用 StreamReader.ReadLine 来读取每个 行。

【讨论】:

  • 其实我使用 File.ReadAllLines 来读取整个文件,然后用 for 循环转换每一行。
猜你喜欢
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 2019-03-31
  • 2017-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多