HDF如何处理删除数据集释放的space而不重新打包

How does HDF handle the space freed by deleted datasets without repacking

我特别指的是 HDF 与使用 Pytables/Pandas 的接口,但我认为这通常适用于 HDF。

我知道 HDF 不会在删除数据集后回收 space,并且您必须使用 h5repack/ptrepack 回收 space。我对该方法的问题是,我发现这些工具非常慢,尤其是对于数 GB(我的文件约为 20 GB)的文件。所以 - 如果你必须 add/delete 具有某种规律性的派生数据集(比如,在调试生成该数据的东西时)

,那是不切实际的

所以 - 我的问题是 space 如果文件没有重新打包,数据集被删除会发生什么?在重新打包文件之前它是否丢失了?下次您尝试向文件 a-la SQL 写入内容时,它是否标记为可用于存储?换句话说 - 释放的 space 是否有用,或者您是否只需要经常重新打包文件?

我不知道 PyTables 背后的代码,所以无法给出官方的 PyTables 开发答案。在 PyTables Google Groups 站点提问,Francesc Alted 可能会回答。 在此期间,我写了一个小测试来锻炼这种行为。下面的示例已被修改以匹配我在 11 月 8 日的评论。它现在创建 3 个 HDF5 文件:

  1. 在第一个中,它创建了 5 个表
  2. 在第二个中,它创建了 5 个表,然后将其删除,然后又创建了 5 个表(具有不同的名称)
  3. 第三个创建了5个表,关闭了文件。重新打开文件,删除 5 个表,然后关闭文件。文件被重新打开,又创建了 5 个表(具有不同的名称)。

生成的文件大小相同。
我的结论:PyTables 足够聪明,可以在新表与删除表的大小相同时回收分配的(但未使用的)space。我怀疑如果新表更大,您可能会得到不同的结果。

下面的简单示例: 文件 _1、_2 和 _3 在我的测试中都是 114 MB。

import tables as tb
import numpy as np

data1  = np.arange(1000000.)
data2  = 2.0*data1
data3  = 3.0*data1

ds_dt = np.dtype({'names':['data1', 'data2', 'data3'],
                  'formats':[(float), (float), (float)] }) 

rec_arr = np.rec.fromarrays([data1, data2, data3], dtype=ds_dt)

with tb.File('SO_58736920_1.h5','w') as h5f:
        tb1 = h5f.create_table('/','test1',obj=rec_arr)
        tb2 = h5f.create_table('/','test2',obj=rec_arr)
        tb3 = h5f.create_table('/','test3',obj=rec_arr)
        tb4 = h5f.create_table('/','test4',obj=rec_arr)
        tb5 = h5f.create_table('/','test5',obj=rec_arr)

with tb.File('SO_58736920_2.h5','w') as h5f:
        tb1 = h5f.create_table('/','test1',obj=rec_arr)
        tb2 = h5f.create_table('/','test2',obj=rec_arr)
        tb3 = h5f.create_table('/','test3',obj=rec_arr)
        tb4 = h5f.create_table('/','test4',obj=rec_arr)
        tb5 = h5f.create_table('/','test5',obj=rec_arr)
        tb1._f_remove()
        tb2._f_remove()
        tb3._f_remove()
        tb4._f_remove()
        tb5._f_remove()  
        tb11 = h5f.create_table('/','test11',obj=rec_arr)
        tb12 = h5f.create_table('/','test12',obj=rec_arr)
        tb13 = h5f.create_table('/','test13',obj=rec_arr)
        tb14 = h5f.create_table('/','test14',obj=rec_arr)
        tb15 = h5f.create_table('/','test15',obj=rec_arr)

with tb.File('SO_58736920_3.h5','w') as h5f:
        tb1 = h5f.create_table('/','test1',obj=rec_arr)
        tb2 = h5f.create_table('/','test2',obj=rec_arr)
        tb3 = h5f.create_table('/','test3',obj=rec_arr)
        tb4 = h5f.create_table('/','test4',obj=rec_arr)
        tb5 = h5f.create_table('/','test5',obj=rec_arr)

with tb.File('SO_58736920_3.h5','r+') as h5f:
        h5f.root.test1._f_remove()
        h5f.root.test2._f_remove()
        h5f.root.test3._f_remove()
        h5f.root.test4._f_remove()
        h5f.root.test5._f_remove()

with tb.File('SO_58736920_3.h5','r+') as h5f:
        tb11 = h5f.create_table('/','test11',obj=rec_arr)
        tb12 = h5f.create_table('/','test12',obj=rec_arr)
        tb13 = h5f.create_table('/','test13',obj=rec_arr)
        tb14 = h5f.create_table('/','test14',obj=rec_arr)
        tb15 = h5f.create_table('/','test15',obj=rec_arr)