我的任务是建立一个平面文件 SKU 数据库,用于存储和处理器速度有限的嵌入式设备。
基本上我需要存储的数据包括以下内容:
SKU 描述 地点 价格 数量
该文件将包含数百万条记录。
最重要的考虑因素是存储空间和检索时间。记录只需要按 SKU 检索,并且是只读的,因此可以按 SKU 对文件进行排序。
我想用 Python 访问这些数据。所以我的问题归结为这个。
是否有现有的 Python 库可以为我提供此功能,还是我需要自己开发?
如果答案归结为我自己,有没有人有建议或很好的参考?
我的任务是建立一个平面文件 SKU 数据库,用于存储和处理器速度有限的嵌入式设备。
基本上我需要存储的数据包括以下内容:
SKU 描述 地点 价格 数量
该文件将包含数百万条记录。
最重要的考虑因素是存储空间和检索时间。记录只需要按 SKU 检索,并且是只读的,因此可以按 SKU 对文件进行排序。
我想用 Python 访问这些数据。所以我的问题归结为这个。
是否有现有的 Python 库可以为我提供此功能,还是我需要自己开发?
如果答案归结为我自己,有没有人有建议或很好的参考?
旧方法是使用简单的键/值数据表,如 gdbm 模块。Python 对此提供了支持,但它没有内置到我机器上的默认 Python 安装中。
一般来说,使用 SQLite。正如其他人所写,它是 Python 的标准配置,并且已经在许多嵌入式系统中使用。
如果记录是固定长度的,那么您可以使用 bisect 模块。文件大小/记录大小给出了文件中的记录数。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 文件并搜索 gzip 文件,但这是您必须测试的空间与时间的权衡。
带有 Python 绑定的SQLite怎么样?它比您需要的多一点,但它是标准软件并且经过良好测试。
我可以建议cdb吗?(Python 绑定:python-cdb。)
它是一种用于只读数据的格式,就像您拥有的一样;它基本上是 256 个巨型哈希表,每个哈希表都可以有不同数量的桶。cdb 最酷的地方在于文件不需要加载到内存中;它的结构使您可以通过mmap
输入所需的位来进行查找。
cdb规范是一个很好的阅读,尤其是因为这些行被格式化以创建一个统一的右边距。:-D
HDF怎么样?如果您不需要 SQL 并且需要快速访问您的数据,那么在 Python 中没有比这更快的方法了......对于数字或结构化数据。
查看Python wiki上的DatabaseInterfaces部分。它是全面的。列出了几个“纯” Python 选项(如SnakeSQL),部署起来更好一些。而且,当然,总是有Berkeley DB之类的,它们非常精益和原始。
老实说,SQLite 可能适合你。如果你真的需要寻求更多的性能,那么你会考虑像 BDB 这样的基于记录的格式。
Andrew Dalke 的答案的一种变体(因此您仍然可以使用二进制搜索快速定位 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