* gran*diccionario de Python con almacenamiento de persistencia para búsquedas rápidas
python 3.6 pickle (6)
Tengo 400 millones de líneas de información clave-valor única que me gustaría estar disponible para búsquedas rápidas en un script. Me pregunto cuál sería una forma hábil de hacer esto. Consideré lo siguiente, pero no estoy seguro si hay una manera de asignar el diccionario al disco y sin usar mucha memoria, excepto durante la creación del diccionario.
- Objeto de diccionario encurtido: no estoy seguro si esta es una solución óptima para mi problema
- Bases de datos de tipo NoSQL: lo ideal es que deseen algo que tenga una dependencia mínima en cosas de terceros y que el valor-clave sea simplemente números. Si sientes que esta sigue siendo la mejor opción, me gustaría escuchar eso también. Puede que me convenza.
Por favor, hágamelo saber si algo no está claro.
¡Gracias! -Abhi
En principio el módulo de shelve hace exactamente lo que usted quiere. Proporciona un diccionario persistente respaldado por un archivo de base de datos. Las claves deben ser cadenas, pero la estantería se encargará de los valores de decapado y decapado. El tipo de archivo de base de datos puede variar, pero puede ser un hash Berkeley DB , que es una excelente base de datos de peso-clave ligero.
Su tamaño de datos suena enorme, por lo que debe hacer algunas pruebas, pero shelve / BDB probablemente esté a la altura.
Nota: El módulo bsddb ha quedado en desuso. Es posible que las estanterías no admitan hashes BDB en el futuro.
Nadie ha mencionado dbm. Se abre como un archivo, se comporta como un diccionario y se encuentra en la distribución estándar.
De los documentos http://docs.python.org/release/3.0.1/library/dbm.html
import dbm
# Open database, creating it if necessary.
db = dbm.open(''cache'', ''c'')
# Record some values
db[b''hello''] = b''there''
db[''www.python.org''] = ''Python Website''
db[''www.cnn.com''] = ''Cable News Network''
# Note that the keys are considered bytes now.
assert db[b''www.python.org''] == b''Python Website''
# Notice how the value is now in bytes.
assert db[''www.cnn.com''] == b''Cable News Network''
# Loop through contents. Other dictionary methods
# such as .keys(), .values() also work.
for k, v in db.iteritems():
print(k, ''/t'', v)
# Storing a non-string key or value will raise an exception (most
# likely a TypeError).
db[''www.yahoo.com''] = 4
# Close when done.
db.close()
Intentaría esto antes que cualquiera de las formas más exóticas, y usar shelve / pickle arrastrará todo a la memoria al cargar.
Aclamaciones
Tim
No creo que debas probar el dictado en escabeche. Estoy bastante seguro de que Python absorberá todo el asunto en todo momento, lo que significa que su programa esperará la E / S más tiempo del que sea necesario.
Este es el tipo de problema para el que se inventaron las bases de datos. Estás pensando en "NoSQL" pero una base de datos SQL también funcionaría. Deberías poder usar SQLite para esto; Nunca he hecho una base de datos SQLite tan grande, pero de acuerdo con esta discusión de los límites de SQLite, 400 millones de entradas deberían estar bien.
¿Cuáles son las características de rendimiento de sqlite con archivos de base de datos muy grandes?
Personalmente uso LMDB y su enlace a Python para unos pocos millones de registros DB. Es extremadamente rápido incluso para una base de datos más grande que la RAM. Está incrustado en el proceso, por lo que no se necesita un servidor. Dependencia se gestionan utilizando pip.
El único inconveniente es que tiene que especificar el tamaño máximo de la base de datos. LMDB va a mmap un archivo de este tamaño. Si es demasiado pequeño, la inserción de nuevos datos generará un error. En general, creas un archivo disperso.
Si desea conservar un diccionario grande, básicamente está buscando una base de datos.
Python viene con soporte incorporado para sqlite3 , que le brinda una solución de base de datos fácil respaldada por un archivo en el disco.
Sin lugar a dudas (en mi opinión), si desea que esto persista, Redis es una excelente opción.
- Instalar redis-server
- Iniciar redis servidor
- Instalar redis python pacakge (pip install redis)
- Lucro.
import redis
ds = redis.Redis(host="localhost", port=6379)
with open("your_text_file.txt") as fh:
for line in fh:
line = line.strip()
k, _, v = line.partition("=")
ds.set(k, v)
Arriba asume un archivo de valores como:
key1=value1
key2=value2
etc=etc
Modifique el script de inserción a sus necesidades.
import redis
ds = redis.Redis(host="localhost", port=6379)
# Do your code that needs to do look ups of keys:
for mykey in special_key_list:
val = ds.get(mykey)
Por qué me gusta Redis.
- Opciones de persistencia configurables.
- Increíblemente rápido
- Ofrece más que solo pares clave / valor (otros tipos de datos)
- @antrirez