odbm
Оптимизация проекта => оптимизация хранилища => dbm => dict style => :-( => odmb => :-)
Бэкенды
- tokyo cabinet (через tokyo-python) — всячески рекомендую, в пару раз быстрее аналогов, файл бд компактнее
- kyoto cabinet (через родную обёртку) — от авторов tokyo-cabinet и по их описанию круче, но по моим тестам тормознее в 2-3 раза
- gdbm
- fsdbm — удобна для хранения крупных документов
- … пишите, если чего-то не хватает
Установка
pip install odbm
репа: bitbucket
Синтаксис
from datetime import datetime, date import odbm # описываем модель class User(odbm.Model): username = odbm.UnicodeProperty(primary_key=True) birthday = odbm.DateProperty(key='b') is_active = odbm.Property(key='a', default=True) is_admin = odbm.Property(key='r', default=False) created = odbm.DateTimeProperty(key='c') __filename__ = 'var/user.odbm.tch' __db_type__ = 'tc' # создаём и сохраняем объект User(username='fizban', birthday=date(1917, 1, 1), created=datetime.now()).save() # в dict-style получится следующее: # db['fizban'] = {'b': timestamp даты, 'c': timestamp времени} # обратите внимание на сокращение ключей (см. key=... в property) # получаем объект по ключу u = User.get('fizban') print u.birthday # datetime.date(1917, 1, 1) # изменяем объект u.is_active = False u.save() # создадим ещё объекы for i in xrange(10): User(username=('test-%i' % i), birthday=date(1950 + i, 1, 1)).save() # все объекты User.find() # получим все объекты c birthday > 1955, отсортированные по username for obj in User.find( filter = lambda u: u.birthday.year > 1955, order = lambda u: u.username): print obj # количество объектов по условию print User.count(lambda u: u.username.startswith('f')) # 1 # удаление объекта print User.count() # 11 User.find_one().delete() print User.count() # 10
Property
- odbm.Property() — сюда можно пихать любые маршализируемые типы (например, {'a': [True, 1, None]})
- odbm.UnicodeProperty() — для unicode строк, чтобы исключить путаницу с латинскими ascii и unicode ключами
- odbm.DateTimeProperty() — datetime.datetime
- odbm.DateProperty() — datetime.date
- odbm.CompressedProperty() — как odbm.Property, но сжимается
- odbm.CompressedUnicodeProperty — как odbm.UnicodeProperty, но сжимается
Производительность
Для теста запишем и считаем в случайном порядке 10к User-ов вышеописаной модели. И сравним с записью/чтением этих же данных в виде cPickle-нных словарей:
seconds to write/read 10000 rows
pickle (write, read): (1.0030829906463623, 0.25429201126098633)
odbm (write, read): (0.99477910995483398, 0.14065694808959961)
pickle file size: 2768704
odbm file size: 1348752
Уменьшение размера файла достигнуто за счёт описанного выше уменьшения длины ключей. Код теста тут.
[offtop] О принципиальной важности компактности файла бд
С год назад мы провели ряд тестов, которые ясно показали: независимо от движка субд, как только используемые файлы не помещаются в кеш файловой системы, скорость рандомных выборок падает на пару порядков. Если кому-то интересны цифры, вот всё что осталось от тех тестов: