Как записать (длинные) целочисленные значения в базу данных Berkeley DB с помощью bsddb3?

Я пытаюсь использовать Berkeley DB для хранения таблицы частот (т.е. хэш-таблицы со строковыми ключами и целочисленными значениями). Таблица будет записана, обновлена ​​и прочитана из Python; поэтому я сейчас экспериментирую с bsddb3. Похоже, он будет делать большую часть того, что я хочу, за исключением того, что он поддерживает только строковые значения?

Если я правильно понимаю, Berkeley DB поддерживает любые двоичные ключи и значения. Есть ли способ эффективно передавать необработанные длинные целые числа в/из Berkeley DB с помощью bsddb3? Я знаю, что могу преобразовать значения в/из строк, и, вероятно, это то, что я в конечном итоге сделаю, но есть ли более эффективный способ? т.е. путем хранения «сырых» целых чисел?


Предыстория: В настоящее время я работаю с большой (потенциально десятками, если не сотнями миллионов ключей) таблицей частот. В настоящее время это реализовано с использованием словаря Python, но я прерываю сценарий, когда он начинает переключаться в виртуальную память. Да, я посмотрел на Redis, но он хранит всю базу данных в памяти. Итак, я собираюсь попробовать Berkeley DB. Я должен иметь возможность повысить эффективность создания с помощью краткосрочного кэширования в памяти. т.е. создайте словарь Python в памяти, а затем периодически добавляйте его в основную таблицу частот Berkeley DB.


person winwaed    schedule 02.05.2012    source источник


Ответы (2)


Вам нужно прочитать данные с языка, отличного от python? Если нет, вы можете просто использовать pickle для длинных целых чисел python и распаковывать их, когда вы читаете их обратно. Возможно, вы сможете (вероятно, сможете) использовать модуль shelve, который сделает это автоматически для вас. Но даже если нет, вы можете вручную выбрать и распаковать значения.

>>> import cPickle as pickle
>>> pickle.dumps(19999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, pickle.HIGHEST_PROTOCOL)
'\x80\x02\x8a(\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7fT\x97\x05p\x0b\x18J#\x9aA\xa5.{8=O,f\xfa\x81|\xa1\xef\xaa\xfd\xa2e\x02.'
>>> pickle.loads('\x80\x02\x8a(\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7fT\x97\x05p\x0b\x18J#\x9aA\xa5.{8=O,f\xfa\x81|\xa1\xef\xaa\xfd\xa2e\x02.')
19999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999L
person Matt Anderson    schedule 02.05.2012
comment
Наверное, другой язык не нужен. Хотя я имею в виду вариант использования C #, это будет утилита импорта (т. е. одноразовый импорт, а не произвольный доступ), поэтому она может работать с текстовыми дампами, созданными Python. Я предполагаю, что pickle будет немного более эффективным, чем форматирование строк? - person winwaed; 02.05.2012
comment
Выглядит нормально, и скрипт работал всю ночь. Похоже, скорость может быть проблемой - возможно, мне нужен больший кеш в памяти. - person winwaed; 03.05.2012

Python struct для преобразования целого числа в байты в Python 3 или строку в Python 2. В зависимости от ваших данных вы можете использовать другой формат упаковки для unsigned long long или uint64_t :

struct.unpack('>Q', my_integer)

Это вернет байтовое представление my_integer в bigendian, которое соответствует лексикографическому порядку, требуемому значениями ключа bsddb. Вы можете использовать более умную функцию упаковки (посмотрите wiredtiger.intpacking), чтобы сэкономить место.

Вам не нужен кеш Python, используйте DBEnv.set_cache_max и set_cache.

person amirouche    schedule 21.08.2015