Python以最高效方法比较两个巨大数据集
我需要比较大量的数据库导出文件,这些文件是xls格式的,目的是每天检查数据的变化(听起来很麻烦,对吧?)。目前我用的方式非常笨拙,先用xlrd把xls文件转换成csv文件,然后再进行比较。
因为这是数据库,我不知道数据在删除某个项目后是否会保持原来的顺序,所以我不能逐行对比文件之间的内容,像用元组这样的方式对我来说并不太合适。
我基本上需要找到每一行可能发生的所有变化,无论这行在导出文件中的位置如何。我唯一能想到的“查找”方式是用SKU作为唯一标识(这是一个来自老旧数据库系统的产品表),但我需要知道的不仅仅是产品被删除或添加,因为价格或其他信息也可能会被修改。
我应该使用集合吗?而且一旦我把这个数据库文件的七万多行加载到一个“集合”中,我的内存使用量会不会非常高?
我考虑过把每一行xls文件作为一个大字符串加载到集合中。这是个高效的主意吗?我可以得到两个集合之间不同的行列表,然后再回去查看原始数据库文件中的那些行,以找到实际的差异。
我从来没有处理过这么大规模的数据解析。我主要是想找一些建议,避免这个过程变得更加复杂,所以我来这里,希望能找到一些对我情况更具体的建议。提前谢谢大家。
3 个回答
你可以把数据放到一个数据库里,然后对比这些数据库。如果你觉得这样更简单的话。
你可能需要考虑的一个关键问题是:你能以某种方式对数据进行排序吗?
排序后的数据集处理起来会简单很多。
附言:75000行数据其实并不算多。任何能放进普通电脑主内存的数据都不算多。可以再加几个零。
我应该使用集合吗?
可能不需要。不过这个问题太模糊,没法给出明确的答案。
如果我把这个数据库文件的七万多行数据加载到一个“集合”里,我的内存使用会不会很夸张?
不会的。七万五千个对象其实不算多,这根本不算大数据。
Python提供了一个工具,叫做difflib,可以帮助你创建一个稍微更优化的算法。
因为你要导出数据库,建议你把它导出为CSV文件,而不是XLS文件。CSV文件要好处理得多。
下面是使用CSV的简单方法。
import csv
with open('yesterday.csv','rb') as yesterday:
rdr= csv.DictReader( yesterday )
baseline= {}
for row in rdr:
baseline[ row['key'] ]= row
with open('today.csv', 'rb' ) as today:
rdr= csv.DictReader( today )
update= {}
for row in rdr:
if baseline[row['key']] == row:
continue
# You have a delta
我用集合来达到这个目的,但尽量把项目数量控制在几百万个以内。正如S.Lott所说,75,000个根本不算什么。我用类似的方式从导入的数据中填充数据库表,同时只发出最少的INSERT和DELETE命令,以便根据上次导入的结果“修补”表格。基本的算法大致是这样的:
lastset = [...] # Populate with the output of the last run
thisset = [...] # The current results
# Remove rows that aren't in the current result set
for row in lastset - thisset:
deleteentry(row[0]) # Where row[0] is the unique key for the table
# Add rows that weren't in the last result set
for row in thisset - lastset:
insertentry(row)
为了让你相信集合操作是快速且内存效率高的,可以试试这个:
>>> a = set(range(10000000))
>>> b = set(range(100, 10000100))
>>> len(a - b)
100
>>> len(b - a)
100
在我的Mac上,这个大约需要1.25GB的内存。确实,这个内存占用很大,但可能是你正在处理的条目数量的100倍以上。这里的集合操作在一秒钟以内就能完成。