我有一个需要执行多次插入操作的应用程序,需要从文件中读取值。 为此,我开始一个事务,准备语句,对值进行绑定(从文件中读取)并执行插入。所有这些都针对文件的所有行循环执行。 一切工作正常,直到我尝试了一个包含数百万行的文件。 在这种情况下,我会看到RAM增加,直到应用程序崩溃为止。
这就是我的实现方式(显然,我在问题上发布了简化代码,没有使用方法,也没有检查错误,等等。)
sqlite3_stmt *stmt;
// OPEN DATABASE
sqlite3 *db;
if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
NSLog(@"NON HO APERTO");
}
//BEGIN TRANSACTION
char * sErrMsg = 0;
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
if(sErrMsg != NULL)
NSLog(@"Error starting transaction");
//PREPARE STATEMENT
char sSQL [BUFFER_SIZE] = "INSERT OR REPLACE INTO table1 (Field2,Field3,Field4,Field5,Field6,Field7,Field8,Field9,Field10,Field11,Field12,Field13,Field14,Field15,Field16,Field17) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
const char * tail = 0;
int res = sqlite3_prepare_v2(db, sSQL, BUFFER_SIZE, &stmt, &tail);
if(res != SQLITE_OK){
NSLog(@"Error preparing the statement: %s",sqlite3_errmsg(db));
}
int counter = 0;
//BIND VALUES AND EXEC
FILE * pFile = fopen ([insertsFilePath_test UTF8String],"r");
while (!feof(pFile)) {
char line [BUFFER_SIZE];
fgets (line, sizeof(char)*BUFFER_SIZE, pFile);
NSString* readLine = [NSString stringWithUTF8String:line];
NSArray *values = [NSJSONSerialization JSONObjectWithData:[readLine dataUsingEncoding:NSUTF8StringEncoding] options:0 error:NULL];
for(int i = 0; i < [values count];i++){
int res = sqlite3_bind_text(stmt, i+1, [values[i] UTF8String], -1, SQLITE_TRANSIENT);
if(res != SQLITE_OK){
NSLog(@"There is an error with the bind of values: %d error code.",res);
}
}
sqlite3_step(stmt);
sqlite3_reset(stmt);
counter++;
//POINT A
}//while
fclose (pFile);
//END TRANSACTION
char * endTrErrMsg = 0;
sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &endTrErrMsg);
if(endTrErrMsg != NULL){
NSLog(@"Error closing transaction");
}
sqlite3_finalize(stmt);
sqlite3_close(db);
NSLog(@"FINISH %d",counter++);
当我发现问题时,我尝试每X行释放一些SQLite内存,并在注释“ // POINT A”处添加如下内容:
if((counter % 80000) == 0 ){
int bytes_freed = sqlite3_release_memory(AMOUNT_OF_MEM_TO_RELEASE);
NSLog(@"Freed %d",bytes_freed);
sqlite3_db_release_memory(db);
}
但是“ bytes_freed”始终为0,并且我什至没有看到RAM图中的微小变化。 我注意到,当进程完成时(所有行已写入并且与db的连接已关闭),系统会正确释放内存。 因此,我尝试关闭事务,释放内存,完成语句,关闭与db的连接,重新打开它,再次准备语句并开始新的事务。 在POINT A处更改代码:
if((counter % 80000) == 0 ){
char * sErrMsg = 0;
sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
if(sErrMsg != NULL){
NSLog(@"Error closing transaction");
}
int bytes_freed = sqlite3_release_memory(AMOUNT_OF_MEM_TO_RELEASE);
NSLog(@"Freed %d",bytes_freed);
sqlite3_db_release_memory(db);
sqlite3_finalize(stmt);
sqlite3_close(db);
if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
NSLog(@"Error opening db");
}
//PREPARE STATEMENT AGAIN
int res = sqlite3_prepare_v2(db, sSQL, BUFFER_SIZE, &stmt, &tail);
if(res != SQLITE_OK){
NSLog(@"Error preparing the statement: %s",sqlite3_errmsg(db));
}
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
if(sErrMsg != NULL){
NSLog(@"Error opening transaction");
}
}
什么都没有改变。 有人知道为什么吗?
有人知道我应该怎么面对这个问题吗?