Мне нужно вести большой список объектов, выбираемых Python. Список слишком велик, чтобы его можно было хранить в ОЗУ, поэтому требуется какой-то механизм базы данных \ подкачки. Мне нужно, чтобы механизм поддерживал быстрый доступ для близких (близлежащих) областей в списке.
В списке должны быть реализованы все функции списка python, но большую часть времени я буду работать последовательно: сканировать некоторый диапазон в списке и во время сканирования решить, хочу ли я вставить \ вытолкнуть некоторые узлы в точке сканирования.
Список может быть очень большим (2–3 ГБ), и не должен все одновременно содержаться в ОЗУ.
Узлы маленькие (100-200 байт), но могут содержать различные типы данных.
Хорошим решением для этого может быть использование BTree, где в ОЗУ загружаются только последние использованные сегменты.
Использование таблиц 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,)
Печать завершилась:
extending to 5000000 nodes took 3.49 seconds
access to 10000 nodes took 0.02 seconds
extending to 5050000 nodes took 3.98 seconds
access to 10000 nodes took 0.01 seconds
extending to 5100000 nodes took 2.54 seconds
access to 10000 nodes took 0.01 seconds
extending to 5150000 nodes took 2.19 seconds
access to 10000 nodes took 0.11 seconds
extending to 5200000 nodes took 2.49 seconds
access to 10000 nodes took 0.01 seconds
extending to 5250000 nodes took 3.13 seconds
access to 10000 nodes took 0.05 seconds
Killed (not by me)