Как HDF обрабатывает пространство, освобожденное удаленными наборами данных, без перепаковки - PullRequest
0 голосов
/ 06 ноября 2019

Я конкретно имею в виду HDF как интерфейс с использованием Pytables / Pandas, но я думаю, что это применимо к HDF в целом.

Я знаю, что HDF не освобождает пространство после удаления набора данных, и что вынеобходимо использовать h5repack / ptrepack, чтобы освободить это пространство. Моя проблема с этим методом заключается в том, что я обнаружил, что эти инструменты работают очень медленно, особенно для файлов объемом несколько гигабайт (мой файл ~ 20 ГБ). Так что - это не практично, если вам нужно с некоторой регулярностью добавлять / удалять производный набор данных (скажем, при отладке того, что делает эти данные)

Итак - мой вопрос, что происходит с этим пространством, гденабор данных был удален, если файл не перепакован? Это просто потеряно, пока вы не перепакуете файл? Он помечен как доступный для хранения в следующий раз, когда вы попытаетесь что-то записать в файл а-ля SQL? Другими словами - это свободное место вообще полезно, или вам просто нужно перепаковывать файл так часто?

1 Ответ

1 голос
/ 07 ноября 2019

Я не знаю код, стоящий за PyTables, поэтому не могу дать официальный ответ по разработке PyTables. Спросите на сайте Google Группы PyTables, и Francesc Alted может ответить. Тем временем я написал небольшой тест для проверки поведения. Пример ниже был изменен, чтобы соответствовать моим комментариям 8 ноября. Теперь он создает 3 файла HDF5:

  1. В первой из них создается 5 таблиц
  2. Во второй создается 5 таблиц, затем удаляются их, а затем создаются еще 5 таблиц. (с разными именами)
  3. В третьем из них создаются 5 таблиц, и файл закрывается. Файл снова открывается, 5 таблиц удаляются, и файл закрывается. Файл открывается снова, создаются еще 5 таблиц (с разными именами).

Полученные файлы имеют одинаковый размер.
Мой вывод: PyTables достаточно умен, чтобы вернуть выделенные (но неиспользованные)) пространство, когда новые таблицы имеют тот же размер, что и удаленные. Я подозреваю, что вы можете получить другой результат, если новые таблицы будут больше.

Простой пример ниже: Файлы _1, _2 и _3 имеют все 114 МБ в моих тестах.

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)
...