2012-01-30 34 views
1

我在Android上使用Sqlite &进行简单的SELECT查询时性能很差,可能还有一些奇怪的行为。 SqliteDatabase.query()仅在1 ms内执行我的查询,但通过Cursor.get*()获取结果需要150 ms以上才能返回8行!如何提高Sqlite/Android中SELECT查询的性能?

我试图在表中查找english所有行其中列word开始与“前缀”(任意字符串),由row列对结果进行排序,并只返回前8个结果。

这里是我的代码:

String columns[] = {"word", "rank"}; 
Cursor cursor = mDB.query("english", columns, "word LIKE '" + prefix + "%'", null, null, null, "rank,word", "8"); 

// It takes only 1 ms to get here 

String word = ""; 
int rank = 0; 
if (cursor.moveToFirst()){ 
    do { 
     word = cursor.getString(0); 
     rank = cursor.getInt(1); 
    } 
    while(cursor.moveToNext()); 
} 

cursor.close(); 

// It takes over 150 ms to get here! 

表定义为english是:

CREATE TABLE en (_id INTEGER PRIMARY KEY, word TEXT, rank INTEGER) 

它包含约65,000项。它也还wordrank指标,有两个第三指数(我越来越绝望!):

CREATE INDEX "rank" ON "en" ("rank" ASC) 
CREATE INDEX "word" ON "en" ("word" ASC) 
CREATE INDEX "word_rank" ON "en" ("word" ASC, "rank" ASC) 

提前感谢!

回答

2

查询方法实际上并不检索所有的数据,当光标在行中移动时,它将检索它。因此,Cursor.move *()方法比查询慢。

这种“延迟加载”的概念有助于节省内存,因为只有在需要时才检索相关数据。

至于表现,你真的没有做错什么。你在模拟器上试试这个吗?也许可以在实际设备上试用并测试性能。

+1

嗨凯恩。在发布我的问题后,我发现瓶颈是cursor.moveToFirst(),这与您所说的有关。我在实际的设备上运行它,但性能非常关键,因为我的应用程序是IME(软键盘),查询查找字典匹配,因此它必须比键盘快。 150+ ms太慢了。 :( – 2012-01-30 03:45:15

+2

Barry,如果你在UI线程上执行查询,150ms速度太慢,你一定要将数据库操作移动到一个单独的线程上,然后将结果发回到UI线程来更新列表。有关此技术的信息请阅读http://developer.android.com/resources/articles/painless-threading.html – 2012-01-30 03:51:25

+0

我曾考虑过,但如果用户在查找之前按空格键,则会出现同步问题线程发现他的话:自动选择功能将插入错误的单词,但我会再次看看这种方法,谢谢 – 2012-01-30 04:50:46