views:

463

answers:

3

I have an app using SQLite3. It's running pretty well, but I would like suggestions on speeding up SQLite (write) access. Most of the database operations are writing triples (int, int, double) of numbers, about 20-50 triples per second. There is an occasional read, but is about as rare as hen's teeth (mostly occurs on loading only).

Does anyone have suggestions on optimizing (or at lease de-pessimizing) the code? Any SQLite3 shortcuts I missed? (Using CoreData is right out because of other stuff in the program.)

I prepare the statement st1 during initialization. It is prepared from

const char *sql = "insert into historic values (?, ?, ?)";
if (sqlite3_prepare_v2(database, sql, -1, &st1, NULL) == SQLITE_OK) ....

This preparation is one-time. The snippet I am using for saving is below (i've removed error checking here for clarity).

-(BOOL) saveHvalue:(int) fid time:(int) t value:(double) v type:(int) ftype
{
    {
     sqlite3_bind_int(st1, 1, fid);
     sqlite3_bind_int(st1, 2, t);
     sqlite3_bind_int(st1, 3, ftype);

     sqlite3_step(st1);
     sqlite3_reset(st1);
     sqlite3_clear_bindings(st1);
    }

    return YES;
}
+4  A: 

Are you batching the writes in a transaction? This alone will save you a lot of time; you can't batch them all in a single transaction or the journal will be gigantic, but 1 transaction per 500-1000 inserts will speed up your code tremendously.

Paul Betts
I'll try that. Thanks.
John Smith
This improved my speed by orders of magnitudes!! Thanks!
John Smith
Of course if you transact 500 records at a time and you insert 50/sec, on a crash you lose (at most) 10 seconds of data (I think uncommitted transactions are rolled back if found in the journal?); but this might probably not be a big issue for you app.
lapo
A: 

Do any of your columns in historic have indices? If they do, it's generally faster to drop the index, insert your stuff, and then re-add the index (if you're adding a LOT all at once).

Dave DeLong
It's also generally unnecessary to have indexes if all you're indexing on is the PK (and since your database is very write-heavy, I'd say you don't need indexes)
Paul Betts
The primary key is (fid, t).
John Smith
A: 

I never usually reply to threads usually but this worked wonders for me (after days trying to optimize in other areas)!

Basically I wrapped my for loop of inserts with:

sqlite3_exec(db, "BEGIN", 0, 0, 0);

for () {
-- inserts --
}

sqlite3_exec(db, "COMMIT", 0, 0, 0);
Codz
Yeah, that's the "Transaction" referred to in @Paul's answer.
Dave DeLong