Android:为什么 Room 这么慢?
Android: Why is Room so slow?
我正在使用 Room 在 Kotlin 中处理一个简单的数据库过程,我无法解释为什么这个过程如此缓慢,主要是在 Android Studio 模拟器上。
我正在做的table是这样的:
@Entity(tableName = "folders_items_table", indices = arrayOf(Index(value = ["folder_name"]), Index(value = ["item_id"])))
data class FoldersItems(
@PrimaryKey(autoGenerate = true)
var uid: Long = 0L,
@ColumnInfo(name = "folder_name")
var folder_name: String = "",
@ColumnInfo(name = "item_id")
var item_id: String = ""
)
我只是想做的是:检查组合 folder/item 是否已经存在,插入一条新记录。如果没有,请忽略它。在模拟器上,插入 100 条记录最多需要 7-8 秒。在真实设备上,它要快得多,但仍然需要大约 3-4 秒,这不是仅 100 条记录的 acceptable。看起来“插入”查询特别慢。
这是实现我刚才描述的过程(在协程中):
val vsmFoldersItems = FoldersItems()
items.forEach{
val itmCk = database.checkFolderItem(item.folder_name, it)
if (itmCk == 0L) {
val newFolderItemHere = vsmFoldersItems.copy(
folder_name = item.folder_name,
item_id = it
)
database.insertFolderItems(newFolderItemHere)
}
}
变量“items”是一个字符串数组。
下面是上述函数的 DAO 定义:
@Query("SELECT uid FROM folders_items_table WHERE folder_name = :folder AND item_id = :item")
fun checkFolderItem(folder: String, item: String): Long
@Insert
suspend fun insertFolderItems(item: FoldersItems)
将循环放在单个事务中应该会显着减少所花费的时间。
原因是每个事务(默认情况下每个 SQL 对数据库进行更改的语句)都会导致磁盘写入。所以你的循环有 100 次磁盘写入。
如果您在循环之前开始事务,然后在循环完成时将事务设置为成功,然后结束事务,则需要单次磁盘写入。
我不确定的是在使用挂起函数(对 Kotlin 不太熟悉)时究竟如何做到这一点。
因此,我建议要么放弃挂起,要么在循环中使用另一个 Dao。
然后有类似的东西:-
val vsmFoldersItems = FoldersItems()
your_RoomDatabase.beginTransaction()
items.forEach{
val itmCk = database.checkFolderItem(item.folder_name, it)
if (itmCk == 0L) {
val newFolderItemHere = vsmFoldersItems.copy(
folder_name = item.folder_name,
item_id = it
)
database.insertFolderItems(newFolderItemHere)
}
}
your_RoomDatabase.setTransactionSuccessful() //<<<<<<< IF NOT set then ALL updates will be rolled back
your_RoomDatabase.endTransaction()
您不妨参考:-
您不妨特别参考runInTransaction
我正在使用 Room 在 Kotlin 中处理一个简单的数据库过程,我无法解释为什么这个过程如此缓慢,主要是在 Android Studio 模拟器上。
我正在做的table是这样的:
@Entity(tableName = "folders_items_table", indices = arrayOf(Index(value = ["folder_name"]), Index(value = ["item_id"])))
data class FoldersItems(
@PrimaryKey(autoGenerate = true)
var uid: Long = 0L,
@ColumnInfo(name = "folder_name")
var folder_name: String = "",
@ColumnInfo(name = "item_id")
var item_id: String = ""
)
我只是想做的是:检查组合 folder/item 是否已经存在,插入一条新记录。如果没有,请忽略它。在模拟器上,插入 100 条记录最多需要 7-8 秒。在真实设备上,它要快得多,但仍然需要大约 3-4 秒,这不是仅 100 条记录的 acceptable。看起来“插入”查询特别慢。
这是实现我刚才描述的过程(在协程中):
val vsmFoldersItems = FoldersItems()
items.forEach{
val itmCk = database.checkFolderItem(item.folder_name, it)
if (itmCk == 0L) {
val newFolderItemHere = vsmFoldersItems.copy(
folder_name = item.folder_name,
item_id = it
)
database.insertFolderItems(newFolderItemHere)
}
}
变量“items”是一个字符串数组。
下面是上述函数的 DAO 定义:
@Query("SELECT uid FROM folders_items_table WHERE folder_name = :folder AND item_id = :item")
fun checkFolderItem(folder: String, item: String): Long
@Insert
suspend fun insertFolderItems(item: FoldersItems)
将循环放在单个事务中应该会显着减少所花费的时间。
原因是每个事务(默认情况下每个 SQL 对数据库进行更改的语句)都会导致磁盘写入。所以你的循环有 100 次磁盘写入。
如果您在循环之前开始事务,然后在循环完成时将事务设置为成功,然后结束事务,则需要单次磁盘写入。
我不确定的是在使用挂起函数(对 Kotlin 不太熟悉)时究竟如何做到这一点。
因此,我建议要么放弃挂起,要么在循环中使用另一个 Dao。
然后有类似的东西:-
val vsmFoldersItems = FoldersItems()
your_RoomDatabase.beginTransaction()
items.forEach{
val itmCk = database.checkFolderItem(item.folder_name, it)
if (itmCk == 0L) {
val newFolderItemHere = vsmFoldersItems.copy(
folder_name = item.folder_name,
item_id = it
)
database.insertFolderItems(newFolderItemHere)
}
}
your_RoomDatabase.setTransactionSuccessful() //<<<<<<< IF NOT set then ALL updates will be rolled back
your_RoomDatabase.endTransaction()
您不妨参考:-
您不妨特别参考runInTransaction