2011-11-25 5 views
1

나는 내가 다른 곳에서 발견 한 관용구를 사용하여 함께 병합하기 위해 노력하고있어 3 개 테이블 각각 32 SQLite는 (3.7.9) 데이터베이스를 가지고있다 (각 DB는 동일한 스키마를 가지고) :SQLite 데이터베이스를 병합하면 나를 미치게 만듭니다. 도움?

attach db1.sqlite3 as toMerge; 
insert into tbl1 select * from toMerge.tbl1; 
insert into tbl2 select * from toMerge.tbl2; 
insert into tbl3 select * from toMerge.tbl3; 
detach toMerge; 

및 전체 데이터베이스 세트에 대해 헹굼 반복. - 900K 행 제 (tbl3)은, 약 850보다 큰 상태에서 테이블

for fn in filelist: 

    completedb = sqlite3.connect("complete.sqlite3") 
    c = completedb.cursor() 

    c.execute("pragma synchronous = off;") 
    c.execute("pragma journal_mode=off;") 

    print("Attempting to merge " + fn + ".") 
    query = "attach '" + fn + "' as toMerge;" 
    c.execute(query) 

    try: 
     c.execute("insert into tbl1 select * from toMerge.tbl1;") 
     c.execute("insert into tbl2 select * from toMerge.tbl2;") 
     c.execute("insert into tbl3 select * from toMerge.tbl3;") 
     c.execute("detach toMerge;") 
     completedb.commit() 
    except sqlite3.Error as err: 
     print "Error! ", type(err), " Error msg: ", err 
     raise 

2, dB 당 비교적 작은 만 50K 행이다 :이 사용 파이썬 및 sqlite3를 모듈을한다. 이제는 네 번째 데이터베이스에 가까워 질 때까지 인서트가 점차적으로 느려지 게됩니다 (결합 된 데이터베이스에 1-3 분마다 추가 된 파일 크기에서 메가 바이트 또는 두 개의 순서로). 그것은 파이썬 경우에, 심지어 INSERTs (.insert; .out foo; sqlite3 complete.dbfoo가 골격이며, here을 찾았습니다.) 테이블을 덤프 해보고 sqlite3 CLI를 사용하여 bash 스크립트에서 결합했습니다. 직접 작업을 수행하지만 정확히 동일한 문제가 발생합니다.

tbl3의 테이블 설정은 UUID, 2 개의 정수 및 4 개의 실제 값을 포함하는 텍스트 필드가 지나치게 까다로운 것은 아닙니다. 내 걱정은 개별 데이터베이스가 같은 수의 행을 가진 파일 크기의 측면에서 더 큰 순서 인 경우 똑같은 문제 (정확하게 네 개의 데이터베이스가 있음)에서 똑같은 문제가 발생했기 때문에 행 수가 있다는 것입니다. (원시 데이터 대신 요약 통계를 저장하여 tbl3의 내용을 상당 부분 정리했습니다). 아니면 내가 작업을 수행하는 방식일까요? 누군가 창문 밖으로 물건을 던지기 전에 내가 가지고있는이 문제에 대해 밝혀 줄 수 있습니까?

답변

1

사용중인 OS 또는 db 파일 크기를 언급하지 않았습니다. Windows는 버전에 따라 2Gb보다 큰 파일에 문제가있을 수 있습니다.

어쨌든이 스크립트는 for 루프를 없애고 왜 sys.argv에서 파일 이름을 얻은 다음 각 병합 데이터베이스에 대해 한 번 실행하면됩니다. 그렇게하면 한 가지 프로세스에서 너무 많은 일을하지 않아도되는 메모리 문제를 처리 할 필요가 없습니다.

다음과 같이 루프를 끝내면 문제가 해결 될 가능성이 높습니다.

c.close() 
completedb.close() 

CLI를 사용하여이 프로세스를 수행하고 모든 db 이후에 종료 할 때도 동일한 현상이 발생한다고 말합니다. 필자는 Python CLI를 사용한다고 가정하고 종료하면 Python을 종료했다가 다시 시작한다는 의미입니다. 이것이 사실이고 4 번째 데이터베이스마다 문제가 계속 발생하면 SQLITE 공유 라이브러리에 문제가있는 것입니다. 그렇게 국가를 지켜서는 안됩니다.

내가 신발에 들어갔다면 attach을 사용하지 않고 파이썬에서 여러 연결을 열어서 커밋 당 약 1000 개 레코드의 데이터를 이동하십시오. 모든 데이터가 파이썬 객체로 들어오고 나가기 때문에 당신의 기술보다 느려질 것입니다. 그러나 나는 또한 믿을만한 것이라고 생각합니다. 전체 db를 열고 두 번째 db를 열어 두 번 복사 한 다음 두 번째 db를 닫습니다. 복사의 경우 SELECT 문에 OFFSET 및 LIMIT을 사용하여 100 개 레코드의 배치를 처리 한 다음 커밋 한 다음 반복합니다. 사실, 나는 또한 completb 레코드를 계산하고, 복사하기 전에 두 번째 db 레코드를 복사 한 다음 completedb 레코드를 복사 한 후 예상 된 값을 복사했는지 확인합니다. 또한 다음 OFFSET의 값을 추적 할 것이므로 커밋 한 직후 텍스트 파일에 기록하므로 언제든지 프로세스를 중단하고 다시 시작할 수 있으며 중단 된 부분을 계속 수행 할 수 있습니다.

+0

마이클, 답변 주셔서 감사합니다. 다시 : 귀하의 질문, 나는 OS X Lion과 Rocks 클러스터 (5.3)의 헤드 노드에서 시도했습니다. 앞서 언급했듯이 문제는 데이터베이스 파일 크기와 별개입니다. 현재 화신에서는 각각 160Mb이지만 문제는 각각 1.6Gb 였을 때와 똑같은 방식으로 발생했습니다. 다시 제안 : 나는 c.close() 및 completedb.close()를 사용하기 전에 시도했지만이 코드에서 벗어났습니다. 문제가 해결되지 않았습니다. 필자도 CLI를 사용하여 수동으로이 작업을 시도해 보았습니다. 시작, 연결, 병합, 종료, 각 파일 반복 등을 시도했습니다. 불운. – Winawer

1

큰 표에 대해 색인/기본 키를 추가하거나 삭제 해보십시오.

관련 문제