Python HDF如何在不重新打包的情况下处理已删除数据集释放的空间

Python HDF如何在不重新打包的情况下处理已删除数据集释放的空间,python,pandas,hdf5,pytables,Python,Pandas,Hdf5,Pytables,我特别提到HDF与使用Pytables/Pandas接口,但我认为这适用于HDF 我知道一旦数据集被删除,HDF就不会回收空间,您必须使用h5repack/ptrepack来回收空间。我使用这种方法的问题是,我发现这些工具非常慢,特别是对于千兆字节(我的文件约为20GB)的文件。因此,如果您必须添加/删除具有某种规律性的派生数据集(例如,在调试生成该数据的东西时),这是不实际的 所以-我的问题是,如果不重新打包文件,删除数据集的空间会发生什么情况?在你重新打包文件之前它就丢失了吗?下次尝试向文件

我特别提到HDF与使用Pytables/Pandas接口,但我认为这适用于HDF

我知道一旦数据集被删除,HDF就不会回收空间,您必须使用h5repack/ptrepack来回收空间。我使用这种方法的问题是,我发现这些工具非常慢,特别是对于千兆字节(我的文件约为20GB)的文件。因此,如果您必须添加/删除具有某种规律性的派生数据集(例如,在调试生成该数据的东西时),这是不实际的


所以-我的问题是,如果不重新打包文件,删除数据集的空间会发生什么情况?在你重新打包文件之前它就丢失了吗?下次尝试向文件a-la SQL写入内容时,是否将其标记为可用于存储?换句话说,释放的空间有用吗,还是只需要每隔一段时间重新打包文件?

我不知道PyTables背后的代码,因此无法给出PyTables开发的正式答案。在PyTables Google Groups网站上提问,Francesc Alted可能会回答。 在此期间,我编写了一个小测试来练习这种行为。下面的例子已经修改,以符合我11月8日的评论。它现在创建3个HDF5文件:

  • 在第一个中,它创建了5个表
  • 在第二个表中,它创建5个表,然后删除它们,然后再创建5个表(使用不同的名称)
  • 在第三个示例中,创建了5个表,并关闭了文件。重新打开文件,删除5个表,并关闭文件。重新打开文件后,将再创建5个表(使用不同的名称)
  • 生成的文件大小相同。
    我的结论是:当新表与已删除表的大小相同时,PyTables足够聪明,可以回收已分配(但未使用)的空间。我怀疑如果新表更大,您可能会得到不同的结果

    下面是一个简单的例子: 在我的测试中,文件1、2和3都是114MB

    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)
    

    我对您的示例进行了扩展,使用Pandas及其HDFStore和to_hdf函数进行了类似的操作,以测试关闭和重新打开文件时会发生什么。有趣的是,至少在熊猫的实现中,它似乎与关键联系在一起。删除某个键上的数据并将其替换似乎会使存档适应新的大小,但删除第一个键并将相同的数据添加到另一个键上会导致存档扩展。阅读您的文章后,我想知道我的示例是否太简单?也许一次性创建、删除和(重新)创建表可以避免“现实世界”中的某些事情(在现实世界中,您可以创建表并关闭,然后重新打开并删除一些表并关闭,然后重新打开并添加更多数据)。因此,我修改了我的示例,将3
    与。。。as:
    语句打开/关闭第二个HDF5文件3次。结果我得到了相同的结果:这两个文件大小相同。显然,熊猫实现PyTables的方式不同。