Shelve слишком медленна для больших словарей, что я могу сделать для повышения производительности?

Я сохраняю таблицу с использованием python, и мне нужно настойчивость.

В основном я храню таблицу в виде строки словаря для чисел. И все хранится с полкой

self.DB=shelve.open("%s%sMoleculeLibrary.shelve"%(directory,os.sep),writeback=True) 

Я использую writeback в True, поскольку я обнаружил, что система имеет тенденцию быть нестабильной, если я этого не делаю.

После вычислений системе необходимо закрыть базу данных и сохранить ее обратно. Теперь база данных (таблица) составляет около 540 МБ, и она занимает возраст. Время взорвалось после того, как стол вырос до 500 МБ. Но мне нужен гораздо больший стол. На самом деле мне нужны два из них.

Я, вероятно, использую неправильную форму настойчивости. Что я могу сделать для повышения производительности?

Ответы

Ответ 1

Для хранения большого словаря пар ключ-значение string : number я бы предложил решение для хранения на основе JSON, такое как MongoDB. У этого есть замечательный API для Python, Pymongo. MongoDB сам по себе является легким и невероятно быстрым, а объекты json изначально будут словарями на Python. Это означает, что вы можете использовать клавишу string в качестве идентификатора объекта, что позволяет использовать сжатое хранилище и быстрый поиск.

В качестве примера того, насколько простым будет код, см. следующее:

d = {'string1' : 1, 'string2' : 2, 'string3' : 3}
from pymongo import Connection
conn = Connection()
db = conn['example-database']
collection = db['example-collection']
for string, num in d.items():
    collection.save({'_id' : string, 'value' : num})
# testing
newD = {}
for obj in collection.find():
    newD[obj['_id']] = obj['value']
print newD
# output is: {u'string2': 2, u'string3': 3, u'string1': 1}

Вам просто нужно преобразовать обратно из unicode, что тривиально.

Ответ 2

Основываясь на моем опыте, я бы рекомендовал использовать SQLite3, который поставляется с Python. Он хорошо работает с большими базами данных и номерами ключей. Миллионы ключей и гигабайт данных не являются проблемой. В этот момент Shelve полностью потеряна. Кроме того, наличие отдельного db-процесса не выгодно, ему просто требуется больше контекстных свопов. В моих тестах я обнаружил, что SQLite3 является предпочтительным вариантом использования при обработке больших наборов данных локально. Запуск локального механизма базы данных, такого как mongo, mysql или postgresql, не дает никакого дополнительного значения, а также медленнее.

Ответ 3

Насколько крупнее? Каковы шаблоны доступа? Какие вычисления вам нужно сделать?

Имейте в виду, что у вас будут некоторые ограничения производительности, если вы не можете держать таблицу в памяти независимо от того, как вы ее выполняете.

Вы можете захотеть взглянуть на SQLAlchemy или напрямую использовать что-то вроде bsddb, но обе из них пожертвуют простотой кода. Однако с SQL вы можете разгрузить часть работы на уровень базы данных в зависимости от рабочей нагрузки.

Ответ 4

Я думаю, что ваша проблема связана с тем, что вы используете writeback=True. документация говорит (акцент мой):

Из-за семантики Python полка не может знать, когда изменяемая постоянная запись словаря изменяется. По умолчанию измененные объекты записываются только при присвоении полки (см. пример). Если опциональный параметр обратной записи установлен в значение Истина, все записи, к которым осуществляется доступ, являются также кэшируется в памяти и записывается обратно на sync() и close(); это может сделать его более удобным для мутирования изменяемых записей в постоянном словарь, но, если доступно много записей, оно может объем памяти для кеша, а он может сделать операцию закрытия очень медленно, так как все доступные записи записываются обратно (нет способа определить, какие доступные записи являются изменяемыми, и какие из них фактически мутировал).

Вы можете избежать использования writeback=True и убедиться, что данные написаны только один раз (вы должны обратить внимание на то, что последующие изменения будут потеряны).

Если вы считаете, что это неправильный вариант хранения (трудно сказать, не зная, как структурированы данные), я предлагаю sqlite3, интегрированный в python (таким образом, очень портативный) и имеет очень приятные характеристики. Это несколько сложнее, чем простое хранилище ключей.

См. другие ответы на альтернативы.