使用 PyTables 索引一个 500 GB 的 HDF5 文件

Using PyTables to index a 500 GB HDF5 file

我想将一个键控的 500GB-800GB table 转储到 HDF5 中,然后检索与特定键匹配的行。

对于 HDF5 文件,所有数据访问等项目都使用一个整数 "row" 数字,所以我似乎必须在 HDF5 之外实现一个“键到行号映射”。

这行得通吗?我需要访问整个 HDF5 "in memory (RAM)" 吗?

任何人都可以告诉我在这种情况下 HDF5 的性能有多差吗?如果有合适的索引,这就是一本巨大的字典,对吧?

我应该使用其他东西吗?

假设你已经在 PyTables 中定义了这个记录类型

class Record(tables.IsDescription):
    row = tables.Int32Col()
    col1 = tables.Int32Col()
    col2 = tables.Float64Col()
    col3 = tables.Float64Col()

常规范围查询可能如下所示:

result = [rec for rec in table if (rec['row'] > 100 and rec['row'] < 200)]

你的 table 不是太大,这很好用。然而对于大的 tables 它会相对较慢,因为每一行都必须被带入 Python space 以评估范围条件。

为了加速这个查询,可以依赖所谓的 in-kernel 查询,它允许使用用 C 编写的 PyTables 内核来检查条件numexpr 库的帮助。

result = [rec for rec in table.where(
            'row > 100 & row < 200')]

您还可以将常规查询与内核查询混合搭配:

result = [rec for rec in table.where(
            'row > 100 & row < 200')] if your_function(rec['col2']) ]

如果您有大的 table 无法放入内存,则加速大约为 2 倍。使用压缩(即 BLOSC、LZF 等)会给你带来轻微的减速,因为解压缩的 CPU 开销小于 I/O 开销(因此对巨大的 table 使用压缩不适合记忆)。

当您使用压缩时,数据集将被分割成块,并且这些块被单独压缩。这意味着如果您查询特定范围(第 100 - 200 行),相应的压缩块将从磁盘加载到内存,然后由内存中的 CPU 解压缩。与不使用压缩或连续存储数据集相比,这将加快速度。 Blosc 是元压缩器,lzf 是 h5py 的默认压缩器。有关 Blosclzf 之间的差异,请参阅此

如果内核查询不够快,您还可以在一个或多个列上创建索引。这样查询将使用二进制搜索而不是顺序扫描。要在 row 列的现有 table 上创建索引,只需 运行:

indexrows = table.cols.row.create_index()

但请注意,索引不会在所有条件下使用(请参阅下面的参考资料)。要检查您的查询是否正确使用了索引,您可以使用 Table.will_query_use_indexing() 方法。

来源:http://www.pytables.org/usersguide/optimization.html#indexed-searches