본인이하는 일에 본질적으로 잘못된 것은 없습니다. 쿼리의 크기에 따라 메모리 사용량이 증가하는 경우 다음 중 하나가 발생합니다.
- 받는 결과에 대한 참조가 누출됩니다. 예를 들어 어딘가에 목록에 넣을 수 있습니다. 네가 그 일을하는지 알았 겠지.
- 데이터베이스 바인딩 또는 기본 라이브러리가 쿼리에서 새 행을 읽는 동안 이전 행의 메모리를 해제하지 않습니다. 이것은 대개 버그입니다. 디버깅 기능이있는 경우 정상적으로 발생할 수 있지만 기본적으로 발생해서는 안됩니다.
기본 라이브러리는 일정량의 데이터를 캐시 할 수 있으며 결과적으로 상당한 메모리 사용량을 볼 수 있지만 구성에 심각한 오류가없는 한 3GB가되어서는 안됩니다.
여러분이하고있는 것을 재현하는 간단한 SQLite 코드가 있습니다. 실행하면 15 백만 행의 사소한 테이블을 만듭니다.이 테이블은 사용중인 버전의 디스크에 약 180MB입니다. 그런 다음이 모든 데이터를 선택하고 결과를 버리며 결과를 검사 할 수 있도록 잠자기합니다. 내 시스템에서 결과 프로세스는 15MB 만 사용합니다.
이
SQLite는이 처리 할 수 있으며, MySQL과 PostgreSQL을 같은 프로덕션 서버 백업 데이터베이스는 할 수 있어야;
는 (데이터베이스를 만드는 것은 약간의 시간이 소요됩니다. 내가 별도의 호출로
create_db
및
read_db
패스를 실행합니다) , 너무. SELECT 결과는
데이터 스트림이며 데이터베이스는 제한없는 크기의 스트림을 쉽게 처리 할 수 있어야합니다.결국 아마 있다고하지만 당신은 수동으로 청크 쿼리를 필요가 없습니다 -
import sqlite3
def create_db(conn):
c = conn.cursor()
c.execute('create table test (i integer)')
conn.commit()
max_val = 15000000
chunk = 1000000
for start in xrange(0, max_val, chunk):
print "%i ..." % start
for i in xrange(start, start + chunk):
c = conn.cursor()
c.execute('insert into test (i) values (?)', (i,))
conn.commit()
def read_db(conn):
c = conn.cursor()
c.execute('select * from test')
for x in xrange(15000000):
c.fetchone()
print "Done"
# Sleep forever, to examine memory usage:
while True:
time.sleep(1)
def go():
conn = sqlite3.connect('test.db')
# Pick one:
create_db(conn)
# read_db(conn)
if __name__ == "__main__":
go()
이
은 귀하의 질문에 대답하지 않습니다,하지만 난 당신이 무슨 일을하는지 아무 문제가 없다는 것을 분명히 확인하고 싶었 해결 방법이 필요합니다.
프로덕션 데이터베이스 바인딩은 요청 크기에 비례하여 메모리를 사용해야하지 않습니다. 주변에 결과를 보관하지 않는 한 더 많은 데이터를 수신하면 이전 데이터가 공개되어야합니다. 모든 데이터베이스 바인딩이이 작업을 제대로 수행하는 것은 아니지만 항상 버그입니다. 데이터베이스 백엔드에서 무한 범위를 선택하고 결과를 점진적으로 처리 할 수 있어야하며 메모리 사용량은 제한없이 근거가되어서는 안됩니다. –
'select *'를 사용하는 것은 거의 불가능합니다. 일부 DB 도구에도 불구하고. 일반적으로 원하는 열을 명시 적으로 나열해야합니다. – paxdiablo