【问题标题】:Comparing 2 arrays with 200,000+ values each比较 2 个数组,每个数组有 200,000+ 个值
【发布时间】:2011-08-22 12:55:29
【问题描述】:

我在 200,000 多个 XML 文件中有一堆数据,这些文件每周都会更新/创建。所以,每周,我都必须解析每个 XML 文件,检查是否有新的 XML 文件正在创建,然后用所有更新的数据更新我的数据库。在这两者之间,如果有新的 XML 文件,那么我的数据库将没有该记录,所以我必须创建一个新行。

这是我的工作流程计划:

  1. 将所有表 X 行 ID 放入数组 A。假设是 200,000 个数值。
  2. 解析每个 XML 文件并收集每个 XML 的 ID(ID 将与我的表 X ID 相同),并存储在数组 B 中。假设现在我有 200,010 个数值,与我当前的表 X 相比有 10 条新记录.
  3. 比较数组 A 和数组 B 以查看哪些值不存在。
  4. 将 10 个新值放入数组 C。
  5. 使用数组 C 中的 10 个新 ID 在表 X 中创建新记录。
  6. 再次解析每个 XML 文件,并将所需的值存储到我的表 X 行列中。
  7. 所以现在我的表 X 将有 200,010 条记录,并且每条记录都会更新,新的 10 条记录现在也将在表 X 中。

我必须这样做的问题是因为我无法获得供应商创建的任何新 XML 文件的任何信息。他们只是给了我一堆文件。

还有更好的方法吗?我担心当他们将两个数组与 200,000+ 值进行比较时,我的系统会崩溃。谢谢。

【问题讨论】:

  • 什么语言?您如何获取 XML 文件?有很多方法。尝试过类似 MD5 的方法来检查文件?还记得存在哪些文件名吗?查看更改日期?
  • 红宝石。 XML 文件都以压缩格式存储,必须解压缩并存储在临时目录中。 ID 也是文件名,也许我可以在步骤 2 中执行此操作。没有更改日期。只是原始 XML 数据。
  • 为什么需要再次解析 XML 文件(第 6 步)?如果 ID 未知,解析每个 XML 文件并 insert 将 xml 内容添加到表中,或者如果 ID 已知,则 更新 xml 内容是否足够?
  • 利用数据库快速定位匹配项的能力。这就是它的用途。正如其他人所提到的,为 md5 值创建一个索引字段。为文件生成 md5 并查看表中是否有它。如果您想真正彻底/偏执,还可以为 XML 的长度创建一个字段并对其进行比较,或者在生成 md5 之前对 XML 进行规范化。但是让数据库比较这些值。无需在内存中创建巨大的数组。

标签: ruby xml performance algorithm


【解决方案1】:

我不得不做类似的事情。最后我是这样做的:

  1. 通过遍历所有 XML 文件中的每条记录、规范化项目(删除换行符、清理空格、替换某些字符),然后对每条记录进行 MD5 求和,为整个设置设置基线。同时导入记录。

  2. 当我获得新数据时,我会遍历记录(SAX 是个好主意),如果记录尚未在数据库中(基于 UID)或已更改(基于 MD5 总和)它被导入。

这非常适合我们通常需要的(大约 350k 记录分布在大约 100 个文件中),但也可以处理(更多)更多数据。它是多种工具的狂野组合,包括 Bash、AWK、sed、grep、出色的 XMLStarlet 和 Ruby,并且迫切需要适当的重写。

【讨论】:

  • 所以使用校验和并使用数据库来完成繁重的工作,而不是使用数组。
  • @mu 基本上是的。还有一些工具的扩散,因为某些任务比其他的更快,但当然这一切都可以在 Ruby 中完成(虽然速度测试并不完全令人鼓舞)。
  • 如果有胆量,可以为 PostgreSQL 构建 PL/Ruby,同时在 Ruby 和数据库中进行。
  • 看起来有很多事情要做!谢谢!
  • 对值进行 200k 查询将比检索列表并在内存中检查它要慢。并且哈希没有任何作用,因为 OP 似乎只需要根据包含的 ID 进行区分。
【解决方案2】:

不要比较 ruby​​ 脚本中的文件。使用 MD5 总和。除非 XML 的内容发生更改,否则这应该可以工作。然后它根本就不是同一个 XML。

【讨论】:

  • 即使供应商每周都会将数据重新导出为 XML 文件。所以我应该使用旧文件的 MD5 与新文件的 MD5 进行比较?我仍然需要将它们放入数组中,对吗?比如,我仍然需要用 Ruby 编写脚本。
  • 是的 MD5 是个好东西!此外,我建议将其全部放入 Ruby 中的哈希表中,以快速检查出现的新事物。
  • 哦,能保证之前导出的数据会导出到同一个文件吗?如果不是,那么 MD5 或其他类似的东西可能是唯一识别“数据”的方式,而不是全部比较。
  • 之前的导出文件名将与新的导出文件名相同。我想你们刚刚给我开了先机!现在,如果新文件011.xml 找不到任何现有的旧文件011.xml 来比较MD5,这意味着我必须根据这个文件创建新记录。对吗?
  • “我仍然需要将它们放入数组中,对吗?就像,我仍然需要用 Ruby 编写脚本。”,不,您不必全部用 Ruby 编写。如果您使用的是 Mac OS 或 Linux,请查看您的操作系统的 md5 命令。如果您在 Windows 上,您可能会找到一个足够简单的。让该实用程序创建校验和并将生成的哈希附加到文本文件中,然后读取它。命令行 md5 应该快很多。例如,我刚刚在 Mac Pro 上使用 /sbin/md5 在不到 1.5 分钟的时间内为 24K+ 个文件生成了哈希值。
【解决方案3】:

一些建议:

  1. 如果 XML 文件很大,请使用 SAX Parser 进行解析(您不需要将整个文件保存在内存中)。
  2. 对数组 A 进行排序,这样就可以使用二分查找了。
  3. 迭代读取每个 XML 文件,如果文件中的 ID 不在数组 A 中,则将其存储在表 X 中(无需保留第二个数组 B)。

【讨论】:

    【解决方案4】:

    看起来是个不错的解决方案。稍作改动就会加快速度。

    在第 3 步中,您“比较数组 A 和数组 B 以查看哪些值不存在”。 我假设您正在遍历数组 B(xml),并在数组 A(数据库)中查找值。

    当您在数组 A 中找到一个值时,请务必将其从数组 A(数据库)中删除,使数组 A 在循环过程中越来越小。

    【讨论】:

      【解决方案5】:

      假设您忽略具有现有 ID 的 XML 文件,而不是导入其中的任何更改(您的问题暗示现有文件不会更改,或者您不关心更改),您的程序的轻微修改将是最优的:

      1. 将数据库中的所有现有 ID 加载到 set,而不是数组中。
      2. 解析每个 XML 文件,提取其 ID,并检查它是否在集合中。
      3. 如果文件不在集合中,则对其进行处理并将其添加到数据库中。

      无需对数据进行两次传递,因为您可以检查文件是否已被处理,如果尚未处理,则立即处理。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-26
        • 1970-01-01
        • 2011-12-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 2011-11-24
        • 1970-01-01
        相关资源
        最近更新 更多