确定传入的 CSV 数据和现有的大型数据集 Mongo 集合之间的差异

Posted

技术标签:

【中文标题】确定传入的 CSV 数据和现有的大型数据集 Mongo 集合之间的差异【英文标题】:Determine differences between incoming CSV data and existing Mongo collection for large data sets 【发布时间】:2021-02-05 03:37:36 【问题描述】:

我有一个传入的 CSV,我试图将它与现有的 mongo 文档集合(Note 对象)进行比较,以确定添加、删除和更新。传入的 CSV 和 mongo 集合非常大,每个都有大约 50 万条记录。

例如。 csv_data

[
 id: 1, text: "zzz"
, 

 id: 2, text: "bbb"
, 

 id: 4, text: "ddd"
, 

 id: 5, text: "eee"
]

Note 对象的 Mongo 集合:

[
 id: 1, text: "aaa"
, 

 id: 2, text: "bbb"
, 

 id: 3, text: "ccc"
, 

 id: 4, text: "ddd"
]

结果我想得到

添加的数组

[
 id: 5, text: "eee"
]

删除数组

[
 id: 3, text: "ccc"
]

一组更新

[
 id: 1, text: "zzz"
]

我尝试使用 select 语句来过滤每个特定差异,但在使用包含所有 500k 记录的真实数据集时它会失败/需要数小时。

additions = csv_data.select|record| !Note.where(id: record[:id]).exists?
deletions = Note.all.select|note| !csv_data.any?|row| row[:id] == note.id
updates = csv_data.select do |record|
    note = Note.where(id: record[:id])
    note.exists? && note.first.text != record[:text]
end

如何更好地优化它?

【问题讨论】:

阅读 N+1 个查询,这是一个反模式 【参考方案1】:

假设:CSV 文件是数据库中在其他时间拍摄的数据的快照,您想要一个差异。

为了得到您想要的答案,您需要阅读数据库中的每条记录。现在,您有效地执行此操作 3 次,一次获取每个统计信息。这是 c.1.5m 数据库调用,如果数据库上的注释比文件中的注释多得多,则可能更多。我会按照以下步骤操作:

    将 CSV 数据读入以 ID 为键的哈希中 读取数据库中的每条记录,并针对每条记录: 如果在 CSV 散列中找到 DB ID,请将其从散列移到 updates 如果在 CSV 哈希中找不到 DB ID,请将其添加到 deletes 当您到达数据库的末尾时,CSV 哈希中仍然存在的任何内容都必须是 addition

虽然它仍然不是超级流畅,但至少您只需执行一次数据库 I/O 而不是 3 次...

【讨论】:

以上是关于确定传入的 CSV 数据和现有的大型数据集 Mongo 集合之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

如何读取非常大的 CSV 的一小部分行。 Pandas - 时间序列 - 大型数据集

iCloud 和现有的“鞋盒”应用核心数据存储

Ruby-on-Rails 3.2:导出包含大型数据集(100,000 条记录)的 CSV

按年份过滤大型数据集

如何在 R 中读取大型数据集 [重复]

Keras 处理无法装入内存的大型数据集