Опции для бинарного хранения плоских файлов только для чтения с использованием Python - PullRequest
1 голос
/ 13 февраля 2010

Мне было поручено настроить базу данных SKU с плоскими файлами для использования на встроенных устройствах с ограниченной памятью и скоростью процессора.

В основном данные, которые мне нужно хранить, состоят из следующего:

SKU Описание Место нахождения Цена Кол-во

Файл будет состоять из нескольких миллионов записей.

Наиболее важные соображения - это место для хранения и время поиска. Записи должны быть извлечены только из SKU, и они будут доступны только для чтения, поэтому файл может быть отсортирован по SKU.

Я хотел бы получить доступ к этим данным с помощью Python. Поэтому мои вопросы сводятся к этому.

Существуют ли библиотеки Python, которые могут предоставить мне эту функцию, или мне нужно свернуть свою собственную?

Если ответ сводится к моему собственному, есть ли у кого-нибудь предложения или хорошие рекомендации для этого?

Ответы [ 6 ]

4 голосов
/ 13 февраля 2010

Старый способ - использовать простую таблицу данных ключ / значение, например модуль gdbm. Python поставляется с поддержкой этого, но он не встроен в установку Python по умолчанию на моем компьютере.

В общем, используйте SQLite. Как писали другие, он входит в стандартную комплектацию Python и уже используется во многих встроенных системах.

Если записи фиксированной длины, вы можете использовать модуль bisect. Размер файла / размер записи дает количество записей в файле. Биссектный поиск выполнит поиск O (log (n)) в файле, и вам потребуется написать адаптер для проверки на равенство. Пока я его не проверял, вот эскиз:

import bisect

RECORD_SIZE = 50

class MatchFirst10Chars(object):
    def __init__(self, word):
        self.word = word
    def __lt__(self, other):
        return self.word < other[:10]

class FileLookup(object):
    def __init__(self, f):
        self.f = f
        f.seek(0, 2)
        self.size = f.tell() // RECORD_SIZE
    def __len__(self):
        return self.size

    def __getitem__(self, i):
        self.f.seek(i*RECORD_SIZE)
        return self.f.read(RECORD_SIZE)


SKU = "123-56-89 "
f = open("data_file")
fl = FileLookup(f)
i = bisect.bisect(fl, MatchFirst10Chars(SKU))

Вы можете дополнительно распаковать файл и выполнить поиск по файлу в формате gzip, но это компромисс между пространством и временем, который вам придется проверить.

4 голосов
/ 13 февраля 2010

Как насчет SQLite с привязками Python? В нем немного больше, чем нужно, но это стандартное программное обеспечение и хорошо проверено.

1 голос
/ 13 февраля 2010

Могу ли я предложить cdb ? (Привязки Python: python-cdb .)

Это формат, используемый для данных только для чтения, как у вас; это в основном 256 гигантских хеш-таблиц, каждая из которых может иметь различное количество сегментов. Крутая вещь в cdb заключается в том, что файл не нужно загружать в память; он структурирован таким образом, что вы можете выполнять поиск, просто mmap вводя нужные вам биты.

cdb spec - хорошее чтение, не в последнюю очередь потому, что строки отформатированы для создания равномерного правого поля. : -D

1 голос
/ 13 февраля 2010

Как насчет HDF ? Если вам не нужен SQL и требуется быстрый доступ к вашим данным, в Python нет ничего быстрее ... для числовых или структурированных данных.

Взгляните на раздел DatabaseInterfaces в Python вики. Это всеобъемлющее. Есть несколько «чистых» опций Python (например, SnakeSQL ), которые немного удобнее для развертывания. И, конечно же, всегда есть Berkeley DB и тому подобное, которые являются сверхлегкими и необработанными.

Честно говоря, SQLite, вероятно, будет хорошо работать для вас. Если вам действительно нужно добиться большей производительности, тогда вы бы выбрали формат, основанный на записях, такой как BDB.

0 голосов
/ 13 февраля 2010

Вариант ответа Эндрю Дальке (так что вы все еще можете использовать бинарный поиск для быстрого поиска SKU), который может уменьшить требования к пространству - это иметь записи фиксированного размера в начале файла (по одному на SKU), а затем все описания и местоположения (как говорят строки с нулевым символом в конце)

Вы можете сэкономить место, не выполняя разметку местоположений и описаний до фиксированной длины. Также вы можете сэкономить место, если есть много повторяющихся мест

Вот пример: говорят, что у вас есть

SKU         16 bytes
Description Variable length
Location    Variable length
Price       4 bytes (up to $42949672.95)
Quantity    4 bytes (up to 4294967295)



 offset          SKU        desc_off   loc_off      Price      Quantity
0x00000000 SKU0000000000001 0x01f78a40 0x01f78a47  0x000003e8  0x000f4240
0x00000020 SKU0000000000002 0x01f78a53 0x01f78a59    ...
...
... # 999998 more records
...
0x01f78a40 Widget\x00
0x01f78a47 Head office\x00
0x01f78a53 Table\x00
0x01f78a59 Warehouse\x00
0 голосов
/ 13 февраля 2010

Простое решение: CPickle . Вы также можете найти похожие вопросы на SO.

...