Pandas PyTables追加:性能和文件大小增加

3

我有超过500个PyTables存储器,每个存储器包含大约300Mb的数据。我希望使用pandas中的append将这些文件合并成一个大的存储器,如下面的代码。

def merge_hdfs(file_list, merged_store):
    for file in file_list:
        store = HDFStore(file, mode='r')
        merged_store.append('data', store.data)
        store.close()

追加操作非常缓慢(每次向merged_store添加一个存储空间需要长达10分钟),而且奇怪的是,每次添加一个存储空间后,merged_store文件的大小似乎会增加1 GB。

根据文档,我已经指定了预期行数,这应该可以提高性能。我读了Improve pandas (PyTables?) HDF5 table write performance,并期望有较长的写入时间,但每300 MB几乎需要10分钟似乎太慢了,而且我无法理解为什么会增加大小。

我想知道是否有什么我错过了?

附加信息:以下是500个PyTables中的一个描述。

/data/table (Table(272734,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Float64Col(shape=(6,), dflt=0.0, pos=1),
  "id": StringCol(itemsize=11, shape=(), dflt='', pos=2),
  "datetaken": Int64Col(shape=(), dflt=0, pos=3),
  "owner": StringCol(itemsize=15, shape=(), dflt='', pos=4),
  "machine_tags": StringCol(itemsize=100, shape=(), dflt='', pos=5),
  "title": StringCol(itemsize=200, shape=(), dflt='', pos=6),
  "country": StringCol(itemsize=3, shape=(), dflt='', pos=7),
  "place_id": StringCol(itemsize=18, shape=(), dflt='', pos=8),
  "url_s": StringCol(itemsize=80, shape=(), dflt='', pos=9),
  "url_o": StringCol(itemsize=80, shape=(), dflt='', pos=10),
  "ownername": StringCol(itemsize=50, shape=(), dflt='', pos=11),
  "tags": StringCol(itemsize=505, shape=(), dflt='', pos=12)}
  byteorder := 'little'
  chunkshape := (232,)
1个回答

3
这基本上是我最近回答的这里的答案。总之,您需要关闭索引store.append('df',df,index=False)。当创建存储时,然后在末尾进行索引。
此外,在合并表格时也要关闭压缩。索引是一项相当昂贵的操作,如果我记得正确,只使用一个处理器。
最后,请确保您使用mode ='w'创建了合并文件,因为所有后续操作都是追加操作,您想开始一个全新的文件。
我也不会预先指定chunksize。相反,在创建最终索引后,使用ptrepack执行压缩,并指定chunksize = auto,它将为您计算。我认为这不会影响写入性能,但会优化查询性能。
您可能还需要将appendchunksize参数(这是写入块大小)调整为更大的数字。
显然,请确保每个追加的表具有完全相同的结构(如果不是,则会引发错误)。我为此创建了一个增强问题:“内部”执行此操作:https://github.com/pydata/pandas/issues/6837

这些表格完全一样吗?当你将它们连接起来时,字符串将全部成为结果表格字符串大小的一部分(这取决于最小值是多少),因此可能会更大。 - Jeff
我已经解析了数据,以便每个表中长字符串的大小限制为固定值(以避免在append操作中出现错误)。这些表并不完全相同,它们的大小也略有不同,但我已经为合并后的表保持了相同的min_itemsize参数,因此我不希望字符串的大小发生变化... - danieleb
你确定每个字段都指定了“min_itemsize”吗?(例如,对于单个文件和合并后的文件进行“ptdump -av”比较。这可能会产生很大的差异。假设在单个文件中未指定“min_itemsize”,但在合并文件中指定了,那么您可以轻松地将其大小加倍(例如,在单个文件中为10,在合并文件中为100)。尽管如此,压缩应该会有很大帮助。因此,也要比较压缩文件。考虑到您的数据集相当大,我肯定会使用“blosc”进行压缩,因为它还可以使查询更快。 - Jeff
因为所有的表都是使用相同的 min_itemsize 参数生成的(并且包含固定最大长度的字符串),我假设合并后的表的字段将自动创建正确的大小,而无需显式传递 min_itemsize 参数给追加函数。我现在已经这样做了,一切似乎都很好。我会遵循您有关压缩的建议,再次感谢您的帮助! - danieleb
另一个建议是,如果您的数据(例如标签,一个大字符串字段)有些稀疏,即它包含在某些行中但不包含在其他行中。可能会更好将其保存在单独的表格中(带有索引键),然后在选择时有效地加入它。或者,可以将这些存储在另一个表格中作为一组子标签(假设这些是一堆子字段),并对主表进行索引。尽管如此,相对于您的时间来说,磁盘是便宜的 :) - Jeff
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接