2012-08-06 57 views
19

Tengo 400 millones de líneas de información única de valor-clave 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 de si hay alguna forma de mapear en disco el diccionario y sin utilizar mucha memoria, excepto durante la creación del diccionario.* large * python dictionary with persistence storage for quick-ups-ups

  1. escabeche objeto de diccionario: No estoy seguro si esto es una solución óptima para mi problema
  2. NoSQL tipo dBases: idealmente quieren algo que tiene la dependencia mínima en materia de la fiesta tercero más el valor clave son simplemente números. Si crees que esta sigue siendo la mejor opción, me gustaría escuchar eso también. Puede ser que me convencerá.

Háganme saber si algo no está claro.

Gracias! -Abhi

+15

Gran diccionario con persistencia = base de datos. –

+0

He oído que couch-db es muy útil para este tipo de cosas (pero nunca tuve que usarlo ...) –

Respuesta

16

Si desea conservar un diccionario grande, básicamente está buscando en una base de datos.

Python viene con compatibilidad integrada para sqlite3, que le ofrece una solución de base de datos fácil de usar respaldada por un archivo en el disco.

+0

Necesito encontrar el enlace a la otra pregunta SO que utiliza una base de datos para grandes secuencias de ADN o algo . –

+0

ok que sería útil – Abhi

+1

implementado esto y funciona bien para la velocidad que necesitamos :) – Abhi

4

No creo que debas probar el dict en escabeche. Estoy bastante seguro de que Python sorberá todo en todo momento, lo que significa que su programa esperará a la E/S más de lo necesario.

Este es el tipo de problema para el que se inventaron las bases de datos. Usted está pensando en "NoSQL" pero también funcionaría una base de datos SQL. Debería poder usar SQLite para esto; Nunca hice una base de datos SQLite tan grande, pero según esta discusión de los límites de SQLite, 400 millones de entradas deberían estar bien.

What are the performance characteristics of sqlite with very large database files?

+0

Bueno SQL funcionaría pero también sería una exageración. – LtWorf

+1

SQLite no es realmente "excesivo". Hay una razón por la que es usado por tantos proyectos. – steveha

5

Sin lugar a dudas (en mi opinión), si desea que esta persista, a continuación, Redis es una gran opción.

  1. Instalar Redis-servidor
  2. inicio del servidor Redis
  3. Instalar Redis thepacakge pitón (PIP instalar Redis)
  4. beneficio.

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) 

asume por encima de un archivos de valores como:

key1=value1 
key2=value2 
etc=etc 

modifique el guión 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 eso me gusta Redis.

  1. opciones persistencia configurables
  2. sorprendentemente rápido
  3. ofrece más de pares acaba de clave/valor (otros tipos de datos)
  4. @antrirez
+0

solo me preguntaba si jugaste con otro almacén de clave-valor y tienes algo que decir sobre ellos ... gracias – Abhi

11

En principio, el módulo de shelve hace exactamente lo que quiere . Proporciona un diccionario persistente respaldado por un archivo de base de datos. Las claves deben ser cadenas, pero shelve se ocupará de los valores de decapado/desatornillado. El tipo de archivo db puede variar, pero puede ser un hash Berkeley DB, que es una excelente base de datos clave-valor ligera.

Su tamaño de datos suena enorme, por lo que debe hacer algunas pruebas, pero shelve/BDB es probable que lo haga.

Nota: El módulo bsddb ha quedado obsoleto. Posiblemente shelve no admitirá hashes de BDB en el futuro.

7

Nadie ha mencionado dbm. Se abre como un archivo, se comporta como un diccionario y está 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() 

me gustaría probar esto antes de cualquiera de las formas más exóticas, y el uso de lado/salmuera se tire todo en la memoria de carga.

Saludos

Tim

+1

En versiones anteriores de Python, este era el módulo 'anydbm'. –

2

Yo personalmente uso LMDB y su python binding de unos pocos millones de registros de base de datos. Es extremadamente rápido incluso para una base de datos más grande que la RAM. Está integrado en el proceso, por lo que no se necesita ningún servidor. La dependencia se gestiona mediante pip.

El único inconveniente es que debe 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.