mercredi 2 septembre 2015

SQLite PRAGMA cache_size iOS

I am working on a Keyboard extension on iOS using Objective C where I am using SQLite. I need to understand a few concepts about SQLite which I didn't get by googling. Let me divide the question in parts.

PART: 1

I have come across a PRAGMA in SQLite called PRAGMA cache_size = pages;

The default size here is 2000 pages. Comparing with the default, according to my understanding,

  • cache_size > 2000 means more memory usage, more speed (than default).
  • cache_size < 2000 means less memory usage, less speed (than default).

Am I correct here?


PART: 2

I am trying to change the cache_size in the following way,

if (sqlite3_exec(sqlite3Database, [@"PRAGMA CACHE_SIZE=50;" UTF8String], NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"Successfully changed cache size");
    }
    else
        NSLog(@"Error: failed to set cache size with message %s.", sqlite3_errmsg(sqlite3Database));

I am using this after opening the database. The following code shows it,

-(void)runQuery:(const char *)query isQueryExecutable:(BOOL)queryExecutable{
// Create a sqlite object.
sqlite3 *sqlite3Database;

// Set the database file path.
NSString *databasePath = [self getDbFilePath];

// Initialize the results array.
if (self.arrResults != nil) {
    [self.arrResults removeAllObjects];
    self.arrResults = nil;
}
self.arrResults = [[NSMutableArray alloc] init];


// Open the database.
BOOL openDatabaseResult = sqlite3_open([databasePath UTF8String], &sqlite3Database);
if(openDatabaseResult == SQLITE_OK) {

    if (sqlite3_exec(sqlite3Database, [@"PRAGMA CACHE_SIZE=50;" UTF8String], NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"Successfully changed cache size");
    }
    else
        NSLog(@"Error: failed to set cache size with message %s.", sqlite3_errmsg(sqlite3Database));
    // Declare a sqlite3_stmt object in which will be stored the query after having been compiled into a SQLite statement.
    sqlite3_stmt *compiledStatement;

    // Load all data from database to memory.
    BOOL prepareStatementResult = sqlite3_prepare_v2(sqlite3Database, query, -1, &compiledStatement, NULL);
    if(prepareStatementResult == SQLITE_OK) {
        // Check if the query is non-executable.
        if (!queryExecutable){
            // In this case data must be loaded from the database.

            // Declare an array to keep the data for each fetched row.
            NSMutableArray *arrDataRow;

            // Loop through the results and add them to the results array row by row.
            while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                // Initialize the mutable array that will contain the data of a fetched row.
                arrDataRow = [[NSMutableArray alloc] init];

                // Get the total number of columns.
                int totalColumns = sqlite3_column_count(compiledStatement);

                // Go through all columns and fetch each column data.
                for (int i=0; i<totalColumns; i++){
                    // Convert the column data to text (characters).
                    char *dbDataAsChars = (char *)sqlite3_column_text(compiledStatement, i);

                    // If there are contents in the currenct column (field) then add them to the current row array.
                    if (dbDataAsChars != NULL) {
                        // Convert the characters to string.
                        [arrDataRow addObject:[NSString  stringWithUTF8String:dbDataAsChars]];
                    }
                }

                // Store each fetched data row in the results array, but first check if there is actually data.
                if (arrDataRow.count > 0) {
                    [self.arrResults addObject:arrDataRow];
                }
            }
        }
        else {
            // This is the case of an executable query (insert, update, ...).

            // Execute the query.
            int executeQueryResults = sqlite3_step(compiledStatement);
            if (executeQueryResults == SQLITE_DONE) {
                // Keep the affected rows.
                self.affectedRows = sqlite3_changes(sqlite3Database);

                // Keep the last inserted row ID.
                self.lastInsertedRowID = sqlite3_last_insert_rowid(sqlite3Database);
            }
            else {
                // If could not execute the query show the error message on the debugger.
                NSLog(@"DB Error: %s", sqlite3_errmsg(sqlite3Database));
            }
        }
    }
    else {
        // In the database cannot be opened then show the error message on the debugger.
        NSLog(@"db error: %s", sqlite3_errmsg(sqlite3Database));
    }

    // Release the compiled statement from memory.
    sqlite3_finalize(compiledStatement);

}

// Close the database.
sqlite3_close(sqlite3Database);

}

But, when I call the method, sqlite3_exec(sqlite3Database, [@"PRAGMA CACHE_SIZE=50;" UTF8String], NULL, NULL, NULL), it always gives SQLITE_OK no matter what I do.

For example, if I do sqlite3_exec(sqlite3Database, [@"abcd bla bla" UTF8String], NULL, NULL, NULL), it returns SQLITE_OK!!

Why is that so?


PART: 3

I want to increase the speed of execution of my queries, but at the same time don't want to use IMDB as the size of the database is huge.

So is PRAGMA page_size = bytes; make any relevance in this case? If yes, then how to do it in Objective C?

Any help is appreciated. Thanks and regards.

Aucun commentaire:

Enregistrer un commentaire