I recently read about SQLite and thought I would give it a try. When I insert one record it performs okay. But when I insert one hundred it takes five seconds, and as the record count increases so does the time. What could be wrong? I am using the SQLite Wrapper (system.data.SQlite)
:
dbcon = new SQLiteConnection(connectionString); dbcon.Open(); //---INSIDE LOOP SQLiteCommand sqlComm = new SQLiteCommand(sqlQuery, dbcon); nRowUpdatedCount = sqlComm.ExecuteNonQuery(); //---END LOOP dbcon.close();
The SQLite docs explains why this is so slow: Transaction speed is limited by disk drive speed because (by default) SQLite actually waits until the data really is safely stored on the disk surface before the transaction is complete. That way, if you suddenly lose power or if your OS crashes, your data is still safe.
The chart shows that on Windows10, content can be read from the SQLite database about 5 times faster than it can be read directly from disk. On Android, SQLite is only about 35% faster than reading from disk.
SQLite doesn't perform well when it comes to user management. It also lacks the ability to handle simultaneous access by multiple users. PostgreSQL performs very well in managing users. It has well-defined permission levels for users that determine what operations they can perform in the database.
The theoretical maximum number of rows in a table is 264 (18446744073709551616 or about 1.8e+19). This limit is unreachable since the maximum database size of 281 terabytes will be reached first.
Wrap BEGIN
\ END
statements around your bulk inserts. Sqlite is optimized for transactions.
dbcon = new SQLiteConnection(connectionString); dbcon.Open(); SQLiteCommand sqlComm; sqlComm = new SQLiteCommand("begin", dbcon); sqlComm.ExecuteNonQuery(); //---INSIDE LOOP sqlComm = new SQLiteCommand(sqlQuery, dbcon); nRowUpdatedCount = sqlComm.ExecuteNonQuery(); //---END LOOP sqlComm = new SQLiteCommand("end", dbcon); sqlComm.ExecuteNonQuery(); dbcon.close();
I read everywhere that creating transactions is the solution to slow SQLite writes, but it can be long and painful to rewrite your code and wrap all your SQLite writes in transactions.
I found a much simpler, safe and very efficient method: I enable a (disabled by default) SQLite 3.7.0 optimisation : the Write-Ahead-Log (WAL). The documentation says it works in all unix (i.e. Linux and OSX) and Windows systems.
How ? Just run the following commands after initializing your SQLite connection:
PRAGMA journal_mode = WAL PRAGMA synchronous = NORMAL
My code now runs ~600% faster : my test suite now runs in 38 seconds instead of 4 minutes :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With