2014-04-14 8 views
2

데이터베이스 테이블을 만들고 모든 레코드를 삽입하는 쿼리로 채워진 큰 SQLite 파일이 있습니다. 파일이 상당히 크고 SQL 파일을 실행하면 예상보다 오래 걸리는 것 같습니다.Objective-C - FMDB - 큰 SQLite 덤프 가져 오기

저는 현재 일하고있는 iPad 앱에 FMDB를 사용하고 있으며, 현재 DB 파일을 새 파일로 바꾸고 싶지만 SQL 파일이 DB 파일과 동일하지는 않습니다. 동일한 헤더 정보 등을 포함하지 않습니다.

이 작업을 수행하는 가장 좋은 방법은 무엇입니까? FMDatabase와 별도의 UPDATE 또는 INSERT 전화를 많이하고, 끝의 시작에서 beginTransactioncommit을하고 고려하는 경우

답변

4

:

[db beginTransaction]; 
// do all of your updates 
[db commit]; 

또는 FMDatabaseQueue를 사용하는 경우, inTransaction 사용

[databaseQueue inTransaction:^(FMDatabase *db , BOOL *rollback) { 
    // do all of your updates 
}]; 

그 중 하나를 사용하지 않으면 삽입 할 때마다 커밋되어 훨씬 느려집니다. 많은 행을 추가하면 차이가 극적으로 나타날 수 있습니다 (예 : 작은 레코드를 많이 추가/업데이트 할 때 성능 차이가 두 자리수로 나타남).


위의 내용은 일련의 별도 SQL 명령을 수행하려는 것으로 가정합니다. 모든 파일이 하나의 파일 (예 : .dump 출력) 인 경우 FMDB는 실제로이 작업을 수행 할 수있는 인터페이스가 없었습니다 (정확하게 SQLite 함수 sqlite3_exec인데도 마찬가지입니다). extra 폴더에 최근에 추가 된 것이 FMDatabaseSplitter이며, SQL의 긴 문자열을 별도의 호출로 분리하여 별도로 호출 할 수 있습니다.

개인적으로 제 3 자 SQL 구문 분석 루틴을 사용하는 것이 신경 쓰이기 때문에 SQLite 함수 sqlite3_exec을 직접 호출해야합니다. 그렇게하려면, 당신은 FMDB sqliteHandle 방법을 사용하여 FMDatabase 개체에서 sqlite3 포인터를 액세스하고 직접 sqlite3_exec 기능과 함께 그것을 사용할 수 있습니다

NSError *error = nil; 
NSString *dumpSQL = [NSString stringWithContentsOfFile:dumpFilePath encoding:NSUTF8StringEncoding error:&error]; 
NSAssert(dumpSQL, @"Loading of SQL failed: %@", error); 

int rc = sqlite3_exec(db.sqliteHandle, [dumpSQL UTF8String], NULL, NULL, NULL); 
if (rc != SQLITE_OK) { 
    NSLog(@"sqlite3_exec error: %@", [db lastErrorMessage]); 
} 

나는 고백한다, 그것은 나에게 약간 긴장하게 대량 SQL을 가져 와서 앱의 데이터베이스로 가져와야합니다. 극도로 조심하지 않으면 SQL에서 무고한 실수로 전체 설치 기반의 응용 프로그램이 손상 될 수 있습니다. 차라리 앱이 JSON 또는 XML 피드를 서버에서 요청한 다음 자체적으로 업데이트를 수행하지만, .dump 출력을 사용하여 FMDB로 앱의 데이터베이스를 업데이트하려는 경우 한 가지 방법입니다.


FMDB 방법론은 executeStatements라고 sqlite3_exec에 대한 래퍼 발표했다 :

BOOL success; 

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);" 
       "create table bulktest2 (id integer primary key autoincrement, y text);" 
       "create table bulktest3 (id integer primary key autoincrement, z text);" 
       "insert into bulktest1 (x) values ('XXX');" 
       "insert into bulktest2 (y) values ('YYY');" 
       "insert into bulktest3 (z) values ('ZZZ');"; 

success = [db executeStatements:sql]; 
+0

아주 좋은 충고입니다 ...하지만 큰 SQL 파일을 사용하여이 작업을 수행 할 방법? – rckehoe

+0

처음에는 모든 데이터를 요청하기 위해 JSON을 사용했지만, 풀다는 데 오랜 시간이 걸렸습니다. 그래서 저는 다른 방식으로 생각해야했습니다. – rckehoe

+1

@rckehoe 충분히 좋습니다. SQL 파일이 훨씬 작 으면 놀랄 것입니다.성능 문제가 실제로 전송 시간에 얼마나 많은지 궁금하고 트랜잭션의 부재 (SQL을 통해 수행하는 경우 BEGIN TRANSACTION 및 COMMIT, 사용하는 경우에는 beginTransaction 및 commit)가 얼마나 많은지 궁금합니다. FMDB 인터페이스). 트랜잭션을 사용하여 업데이트 프로세스 중에 얼마나 많은 성능 향상을 달성 할 수 있는지는 매우 놀랍습니다. 저는 실용 주의자입니다. 그렇다면 SQL 파일을 사용하면 도움이됩니다.하지만 정말 문제가된다면 놀라실 것입니다. – Rob