developer tip

Python sqlite3에서 기존 db 파일을 메모리에로드하는 방법은 무엇입니까?

optionbox 2020. 12. 27. 10:38
반응형

Python sqlite3에서 기존 db 파일을 메모리에로드하는 방법은 무엇입니까?


sqlite3몇 가지 광범위한 계산을해야하는 기존 db 파일이 있습니다. 파일에서 계산을 수행하는 것은 고통스럽고 느리고 파일이 크지 않기 때문에 (~ 10 MB) 메모리에로드하는 데 문제가 없습니다.

계산 속도를 높이기 위해 기존 파일을 메모리에로드하는 Python 방식이 있습니까?


다음은 플라스크 애플리케이션을 위해 작성한 코드입니다.

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

sqlite3.Connection.iterdump"[r]은 데이터베이스를 SQL 텍스트 형식으로 덤프하는 반복자를 반환합니다. 나중에 복원하기 위해 메모리 내 데이터베이스를 저장할 때 유용합니다.이 함수는 .dumpsqlite3 쉘 명령 과 동일한 기능을 제공합니다 ."

이러한 반복기를 가져 와서 디스크 기반 데이터베이스를 메모리 기반 데이터베이스로 덤프하면 계산할 준비가 된 것입니다. 계산이 완료되면 다른 방법으로 디스크에 덤프하십시오.


먼저 관찰하고있는 속도 저하의 원인이 무엇인지 알아 내야합니다. 테이블에 글을 쓰고 있습니까? 불필요한 임시 결과를 디스크에 저장하지 않도록 충분히 큰 트랜잭션 내에 쓰기 작업을 수행하고 있습니까? 임시 테이블로 이동하도록 쓰기를 변경할 수 있습니까 (사용 pragma temp_store=memory)? 함께 살 수 있습니까 pragma synchronous=off?

이 기능이 Python 모듈에 노출되어 있다고 생각하지 않지만 sqlite에는 사용자가 요청하는 것과 똑같은 백업 API 가 있습니다. 한 데이터베이스에서 다른 데이터베이스로 복사하는 방법 (둘 중 하나는 메모리 내일 수 있음) 사용자가 볼 수있는 테이블 열거없이 거의 자동으로 작동합니다. (어쩌면 APSW 가 이것을 노출합니까?)

또 다른 옵션은 램 디스크를 만들고 (환경을 충분히 제어 할 수있는 경우) 파일을 여기에 복사하는 것입니다.


파이썬 래퍼를 사용해야한다면 두 단계, 읽기 및 쓰기 솔루션보다 더 나은 솔루션은 없습니다. 그러나 버전 3.7.17부터 SQLite에는 메모리 매핑 I / O를 사용하여 디스크 콘텐츠에 직접 액세스 할 수있는 옵션이 있습니다. sqlite mmap

mmap을 사용하려면 래퍼가 제공하지 않으므로 C 인터페이스를 사용해야합니다.

또 다른 하드웨어 솔루션 인 메모리 디스크가 있습니다. 그러면 편리한 파일 IO와 메모리 속도가 있습니다.


In python의 코드 예제를 포함하여 이전에 이미 대답 했습니다. 연결하기 전에 sqlite db를 메모리에 완전히로드하려면 어떻게해야합니까?

운영 체제에 대해서는 언급하지 않았지만 Windows XP의 한 가지 문제점은 메모리 용량에 관계없이 기본적으로 10MB 파일 캐시를 사용한다는 것입니다. (이는 시스템이 64MB 등으로 나왔을 때 이치에 맞았습니다.) 이 메시지에는 여러 링크가 있습니다.

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


다음은 SQLite db를 메모리로 읽는 비교적 간단한 방법입니다. 데이터 조작과 관련된 선호도에 따라 Pandas 데이터 프레임을 사용하거나 메모리 내 sqlite3 데이터베이스에 테이블을 작성합니다. 마찬가지로 데이터를 조작 한 후 동일한 df.to_sqlite 접근 방식을 사용하여 결과를 다시 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')

어때 sqlite3.Connection.backup(...)? "이 방법은 다른 클라이언트가 액세스하는 동안 또는 동일한 연결에서 동시에 SQLite 데이터베이스를 백업합니다." 가용성 : SQLite 3.6.11 이상. 버전 3.7의 새로운 기능.

import sqlite3

source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)

sqlite는 메모리 내 데이터베이스를 지원합니다.

파이썬에서는 : memory : 데이터베이스 이름을 사용합니다.

Perhaps you could open two databases (one from the file, an empty one in-memory), migrate everything from the file database into memory, then use the in-memory database further to do calculations.


With the solution of Cenk Alti, I always had a MemoryError with Python 3.7, when the process reached 500MB. Only with the use of the backup functionality of sqlite3 (mentioned by thinwybk), I was able to to load and save bigger SQLite databases. Also you can do the same with just 3 lines of code, both ways.

ReferenceURL : https://stackoverflow.com/questions/3850022/how-to-load-existing-db-file-to-memory-in-python-sqlite3

반응형