У меня есть приложение, которое должно делать несколько вставок, считывая значения из файла.Для этого я начинаю транзакцию, подготавливаю оператор, выполняю привязку со значениями (считывается из файла) и выполняю вставку.Все это в цикле для всех строк файла.Все работало нормально, пока я не попробовал файл с миллионом строк.В этом случае я вижу увеличение ОЗУ до сбоя приложения.
Вот как я это реализовал (очевидно, я публикую упрощенный код по моей проблеме, без использования методов, без проверки на ошибки, ecc ..).
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++);
Когда я обнаружил проблему, я попытался освободить часть памяти SQLite каждые X строк, добавив в комментарии "// 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, и я не увидел даже небольшого изменения в графике оперативной памяти.Я заметил, что после завершения процесса (все строки записаны и соединение с БД закрыто) система освобождает память правильно.Поэтому я попытался закрыть транзакцию, освободить память, завершить оператор, закрыть соединение с БД, снова открыть его, снова подготовить оператор и начать новую транзакцию.Изменение кода в ТОЧКЕ А:
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");
}
}
Ничего не изменилось.Кто-то знает почему?
Кто-нибудь знает, как мне следует столкнуться с проблемой?