2010-10-03 9 views
46

Tengo un archivo db sqlite3 existente, en el que tengo que hacer algunos cálculos exhaustivos. Hacer los cálculos desde el archivo es extremadamente lento, y como el archivo no es grande (~ 10 MB), entonces no debería haber ningún problema para cargarlo en la memoria.¿Cómo cargar el archivo db existente en la memoria en Python sqlite3?

¿Hay alguna forma pitonica de cargar el archivo existente en la memoria para acelerar los cálculos?

Respuesta

88

Aquí es el fragmento que escribí para mi aplicación frasco:

import sqlite3 
from StringIO import StringIO 

def init_sqlite_db(app): 
    # Read database to tempfile 
    con = sqlite3.connect(app.config['SQLITE_DATABASE']) 
    tempfile = StringIO() 
    for line in con.iterdump(): 
     tempfile.write('%s\n' % line) 
    con.close() 
    tempfile.seek(0) 

    # Create a database in memory and import from tempfile 
    app.sqlite = sqlite3.connect(":memory:") 
    app.sqlite.cursor().executescript(tempfile.read()) 
    app.sqlite.commit() 
    app.sqlite.row_factory = sqlite3.Row 
2

sqlite admite bases de datos en memoria.

En python, utilizaría un nombre de base de datos : memoria: para eso.

Quizás podría abrir dos bases de datos (una del archivo, una vacía en la memoria), migrar todo de la base de datos a la memoria, luego usar la base de datos en memoria para hacer cálculos.

+4

¿Existe una forma rápida de transferir la base de datos? Mover cada mesa no es elegante. –

+0

Esta respuesta básicamente solo repite la pregunta. – madoki

15

sqlite3.Connection.iterdump "[r] crea un iterador para volcar la base de datos en formato de texto SQL. Útil al guardar una base de datos en memoria para su posterior restauración .Esta función proporciona las mismas capacidades que el comando .dump en el shell sqlite3."

Obtenga este iterador y volque la base de datos basada en disco en una basada en memoria, y estará listo para calcular. Cuando termine el cálculo, simplemente vuelca al revés al disco.

+3

Eso es genial, pero ¿cómo se restaura ese volcado en una base de datos de memoria? –

+0

Conéctese a la base de datos basada en archivos y vacíe al revés. No es bonito, pero si tus cálculos son realmente caros, valdrá la pena. –

+3

Wohoo! Funciona de maravilla. –

8

Primero debes probar y descubrir qué está causando la lentitud que estás observando. ¿Estás escribiendo en tablas? ¿Sus escritos están lo suficientemente grandes como transactions para que no guarde innecesarios resultados temporales en el disco? ¿Puedes cambiar las escrituras para ir a tablas temporales (con pragma temp_store=memory)? ¿Puedes vivir con pragma synchronous=off?

No creo que esta funcionalidad esté expuesta en el módulo de Python, pero sqlite tiene un backup API que suena exactamente como lo que está pidiendo: una forma de copiar de una base de datos a otra (cualquiera de las cuales puede ser base de datos en memoria) que funciona prácticamente de manera automática sin ninguna enumeración de tablas visible por el usuario. (Tal vez APSW expone esto?)

Otra opción es crear un disco RAM (si tiene suficiente control del medio ambiente) y copiar el archivo allí.

+0

Gracias por la respuesta profunda. Solo estoy leyendo, así que un simple truco de copiar a memoria servirá. –

4

Esto ya ha sido respondida antes, incluyendo ejemplos de código en In python, how can I load a sqlite db completely to memory before connecting to it?

Usted no menciona sistema operativo, pero uno de gotcha de Windows XP es que toma por defecto un archivo de caché de 10 MB, sin importar la cantidad de memoria que tienen . (Esto tenía sentido en los días en que los sistemas venían con 64 MB, etc.). Este mensaje tiene varios enlaces:

http://marc.info/?l=sqlite-users&m=116743785223905&w=2

4

Aquí es una forma relativamente sencilla de leer una base de datos SQLite en la memoria. Dependiendo de sus preferencias con respecto a la manipulación de datos, puede utilizar el marco de datos de Pandas o escribir su tabla en una base de datos sqlite3 en memoria. Del mismo modo, después de manipular sus datos, utiliza el mismo enfoque df.to_sqlite para almacenar sus resultados nuevamente en una tabla db.

import sqlite3 as lite 
from pandas.io.sql import read_sql 
from sqlalchemy import create_engine 

engine = create_engine('sqlite://') 
c = engine.connect() 
conmem = c.connection 
con = lite.connect('ait.sqlite', isolation_level=None) #Here is the connection to <ait.sqlite> residing on disk 
cur = con.cursor() 
sqlx = 'SELECT * FROM Table' 
df = read_sql(sqlx, con, coerce_float=True, params=None) 

#Read SQLite table into a panda dataframe 
df.to_sql(con=conmem, name='Table', if_exists='replace', flavor='sqlite') 
3

si tenemos que usar un contenedor de python, entonces no hay mejor solución que la solución de dos pasos, de lectura y escritura. , pero a partir de la versión 3.7.17, SQLite tiene la opción de acceder al contenido del disco directamente mediante E/S mapeadas en memoria. sqlite mmap

si desea utilizar mmap, debe utilizar la interfaz C, ya que no hay envoltorio.

y hay otra solución de hardware, el disco de memoria.entonces tiene el conveniente archivo IO y la velocidad de la memoria.

Cuestiones relacionadas