iOS上SQLite插入的内存问题

时间:2019-02-27 16:13:07

标签: ios objective-c sqlite memory-management sql-insert

我有一个需要执行多次插入操作的应用程序,需要从文件中读取值。 为此,我开始一个事务,准备语句,对值进行绑定(从文件中读取)并执行插入。所有这些都针对文件的所有行循环执行。 一切工作正常,直到我尝试了一个包含数百万行的文件。 在这种情况下,我会看到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");
        }
    }

什么都没有改变。 有人知道为什么吗?

有人知道我应该怎么面对这个问题吗?

0 个答案:

没有答案
相关问题