简而言之:
使用query()
执行23770次SELECT查询并使用Cursor
检索结果需要 7秒。通过使用compileStatement()
编辑语句并调用simpleQueryForString()
,我能够将时间缩短到 1秒。
有没有办法在不使用compileStatement()
的情况下获得类似的性能,因为仅当输出为1x1表时,compileStatement()仅限于检索结果?
更多信息:
我有一个Android应用程序,它使用带有以下架构的表的SQLite数据库:
CREATE TABLE testtable(
id number primary key,
sentence text not null
);
该表以id为索引 我的应用程序的一部分是将 id 的数组作为输入,并从表 testtable 中检索相应的句子。
我开始使用query()方法,花费 7秒为 23770 的数组检索句子 ID 秒。 (在7秒内查询23770次)
我试图提高性能,我发现SQLiteStatement compileStatement(String sql)
可以通过事先编译语句来提高性能。并且由于SQLiteStatement
有一个方法String simpleQueryForString()
来检索结果,如果输出是1 x 1表(当前满足我的用例),我使用它。
改善是巨大的。它可以在 1秒中完成相同的 23770 查询。
虽然我现在可以使用它,但是查询可能会变得复杂,输出可能会占用更多行和列,这将使我使用query()
方法。
所以我的问题是:有没有办法在不使用compileStatement()
的情况下优化查询并获得类似的效果?
这是我正在测试的代码(使用compileStatement()
的代码已注释):
public class DBMan extends SQLiteAssetHelper{
SQLiteDatabase db;
public DBMan(Context context){
super(context, "my.db", null, 1);
db = this.getReadableDatabase();
}
public String[] getSentences(Integer[] idList){
String[] result = new String[idList.length];
Cursor cur = null;
long timeStart = System.nanoTime();
try {
db.beginTransaction();
/* SQLiteStatement selStmt = db.compileStatement("SELECT sentence FROM testtable WHERE id=?"); */
for (int i = 0; i < idList.length; i++) {
// Querying using compileStatement() and simpleQueryForString()
/*
selStmt.clearBindings();
selStmt.bindLong(1, idList[i]);
result[i] = selStmt.simpleQueryForString();
*/
// Querying using query() and Cursor
cur = db.query(
"testtable",
new String[]{"sentence"},
"id = ?",
new String[]{String.valueOf(idList[i])},
null, null, null
);
if (cur.moveToFirst()) {
result[i] = cur.getString(0);
}
if (cur != null) {
cur.close();
}
}
db.setTransactionSuccessful();
}
finally {
db.endTransaction();
}
long totalTime = System.nanoTime() - timeStart;
Log.i("MYAPP", "DB total query time: "+totaltime/1000000000.0+" sec");
return result;
}
}
我正在使用SQLiteAssetHelper这是SQLiteOpenHelper
的扩展名。我正在使用它在首次运行时从assets文件夹复制我的数据库文件,而不是创建它。
我使用了事务,虽然我只做了选择查询,因为它减少了获取和删除的共享锁的数量(see here)。