我需要维护大量 python pickleable 对象。列表太大,无法全部存储在 RAM 中,因此需要一些数据库\分页机制。我需要该机制支持对列表中关闭(附近)区域的快速访问。
该列表应该实现所有 python-list 功能,但大多数时候我将按顺序工作:扫描列表中的某个范围,并在扫描时决定是否要在扫描点插入\弹出一些节点。
该列表可能非常大(2-3 GB),不应一次全部包含在 RAM 中。节点很小(100-200 字节),但可以包含各种类型的数据。
一个很好的解决方案可能是使用 BTree,其中只有最后访问的存储桶被加载到 RAM 中。
使用 SQL 表并不好,因为我需要实现复杂的索引键机制。我的数据不是表格,它是一个简单的 python 列表,具有在特定索引中添加元素以及从特定位置弹出元素的功能。
我尝试了ZODB和zc.blist,它们实现了一个基于 BTree 的列表,可以存储在 ZODB 数据库文件中,但我不知道如何配置它,以便上述功能可以在合理的时间内运行。我不需要所有的多线程\事务处理功能。除了我的单线程程序外,没有其他人会接触数据库文件。
谁能解释我如何配置 ZODB\zc.blist 以使上述功能运行得更快,或者向我展示一个不同的大列表实现?
我尝试过的一些快速而肮脏的代码:
import time
import random
NODE_JUMP = 50000
NODE_ACCESS = 10000
print 'STARTING'
random_bytes = open('/dev/urandom', 'rb')
my_list = list()
nodes_no = 0
while True:
nodes_no += NODE_JUMP
start = time.time()
my_list.extend(random_bytes.read(100) for i in xrange(NODE_JUMP))
print 'extending to %s nodes took %.2f seconds' % (nodes_no, time.time() - start)
section_start = random.randint(0, nodes_no -NODE_ACCESS -1)
start = time.time()
for index in xrange(section_start, section_start + NODE_ACCESS):
# rotate the string
my_list[index] = my_list[index][1:] + my_list[index][0]
print 'access to %s nodes took %.2f seconds' % (NODE_ACCESS, time.time() - start,)
打印结束于:
扩展到 5000000 个节点耗时 3.49 秒 访问 10000 个节点耗时 0.02 秒 扩展到 5050000 个节点耗时 3.98 秒 访问 10000 个节点耗时 0.01 秒 扩展到 5100000 个节点耗时 2.54 秒 访问 10000 个节点耗时 0.01 秒 扩展到 5150000 个节点耗时 2.19 秒 访问 10000 个节点耗时 0.11 秒 扩展到 5200000 个节点耗时 2.49 秒 访问 10000 个节点耗时 0.01 秒 扩展到 5250000 个节点耗时 3.13 秒 访问 10000 个节点耗时 0.05 秒 被杀(不是我)