We want to migrate our App from Room to SQLDelight to reuse it on iOS (it is a Multiplatform project). I noticed however that SQLDelight is much slower than Room. For some queries it is around 10 times slower. I did some in depth testing with insert statements which take ~5ms on average with Room and ~25ms on average with SQLDelight. I checked (and adapted) the query so that they are exactly identical.
I also checked some PRAGMAs and found that SQLDelight uses Pragma SYNCHRONOUS=1 (NORMAL) whereas Room uses 2 (FULL) and SQLDelight uses JOURNAL_MODE=TRUNCATE whereas Room uses WAL. I changed these settings in the SQLDelight setup to be equal to Room and the performance got a bit better but still ~20ms for the test described above.
Does anyone have an idea what causes the difference? Any help is appreciated.
You've reached SQL Status Level 80: LEGENDARY. The above tips will optimize your SQL queries, but SQLBot will boost your efficiency even more. SQLBot bypasses one of the biggest SQL slowdowns of all: Procrastination! Here’s the issue: Maybe we’re afraid of seeing bad results.
Additionally: in the original post we found out that using SQLiteStatement directly was slightly faster than using db.execSQL (), and since Room’s generated code for insertions uses SQLiteStatement, let’s just compare apples to apples. Room seems a little slower than manually using SQLiteStatement for the simple case.
SQL performance tuning means you have to see the forest and the trees. You can’t work on your queries without keeping the tables and indexes in mind. Here’s the tip: After you’ve sorted out the tables and indexes, zoom out to consider all essential queries.
You can improve your query efficiency by using a tool to analyze and optimize your SQL queries. SQL query planning tools look for performance problems and give you data to better understand how your queries are measuring up.
The reason for the slower performance seems to be the journal mode and synchronous settings indeed. I didn't recognise this before because my changes didn't work the intended way.
So the current answer for me is to set journal mode to WAL and synchronous to 2 which are the defaults for Room. I could only accomplish it by using the following code in the DriverFactory, if someone has a cleaner solution I'm happy to see it.
actual class DriverFactory(private val context: Context) {
actual fun createDriver(): SqlDriver {
return AndroidSqliteDriver(
schema = Database.Schema,
context = context,
name = "Database.db",
callback = object : AndroidSqliteDriver.Callback(Database.Schema) {
override fun onConfigure(db: SupportSQLiteDatabase) {
super.onConfigure(db)
setPragma(db, "JOURNAL_MODE = WAL")
setPragma(db, "SYNCHRONOUS = 2")
}
private fun setPragma( db: SupportSQLiteDatabase, pragma: String) {
val cursor = db.query("PRAGMA $pragma")
cursor.moveToFirst()
cursor.close()
}
}
)
}
}
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