确定传入的 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 - 时间序列 - 大型数据集