加速Android上的数据库查询

时间:2013-02-06 09:31:32

标签: android database sqlite

我在Android上使用SQLiteDatabase(http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html

使用SQLite

我正在开发一个圣经应用程序,它有一个包含以下列的表:

  • book:int
  • chapter:int
  • 诗:int
  • wordIdx:int
  • strongId:string
  • word:string

每个句子被分解为一系列strongId /单词对,因此wordIdx用于对单词进行排序,strongId只是一个索引到一个索引,而单词是句子中的单词。

所以我有300,000行 瓶颈似乎是我查询每个经文的单词列表:

我的SQL实际上是这样的:

SELECT strongId, word FROM ? WHERE book=? AND chapter=? AND verse=?

以下是代码:

Cursor cursor = mBible.database().rawQuery("SELECT " + KEY_STRONGID + "," + KEY_WORD + " FROM " + tableName() + " WHERE " + KEY_BOOK + "=? AND " + KEY_CHAPTER + "=? AND " + KEY_VERSE + "=?" , new String[] { String.valueOf(mChapter.mBook.index()), String.valueOf(mChapter.index()), String.valueOf(verse) });

cursor.moveToFirst();

mWordList = new ArrayList<Word>();
do {
    mWordList.add(new Word(cursor.getString(1), cursor.getString(0)));
} while (cursor.moveToNext());

现在,我已经尝试将每一章放入其自己的临时视图(使用CREATE TEMP VIEW),在我的示例中将记录减少到大约400,但仍然需要很长时间才能查询

以30秒的顺序生成两个章节的文本以显示给用户(使用临时视图而不使用临时视图)。如果我设置一个虚拟的单词列表以避免数据库查询,则大约需要5秒钟。

如何改善这种性能?似乎临时观点对我的表现没有影响。

2 个答案:

答案 0 :(得分:1)

视图不会改变查询的性能;它只保存查询本身,而不是查询的结果

如果您使用桌面计算机上的sqlite3命令行工具打开数据库,则可以使用EXPLAIN QUERY PLAN command检查查询的效率。

没有任何索引,您查询始终扫描整个表:

> sqlite3 bible.db
SQLite version 3.7.15.2 2013-01-09 11:53:05
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SCAN TABLE MyTable (~1000 rows)

使用三个查找字段的索引,SQLite可以在索引中进行快速搜索,并且只需要从表中读取匹配的记录:

sqlite> CREATE INDEX b_c_v ON MyTable(book, chapter, verse);
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SEARCH TABLE MyTable USING INDEX b_c_v (book=? AND chapter=? AND verse=?) (~8 rows)

如果您创建覆盖索引(在查询中使用所有字段,首先查找字段),SQLite根本不需要从表中读取。但是,这并没有比普通索引提供更大的加速,并且可能不值得额外的存储成本:

sqlite> CREATE INDEX cov ON MyTable(book, chapter, verse, strongId, word);
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SEARCH TABLE MyTable USING COVERING INDEX cov (book=? AND chapter=? AND verse=?) (~8 rows)

请注意,SQLite在查询中每个表最多只能使用一个索引,因此创建多个索引并不总是有意义的。 使用EXPLAIN QUERY PLAN检查实际使用的索引,以及是否可以创建一些索引来优化大多数查询。

另请参阅Query Planning文档。

答案 1 :(得分:0)

我最终创建了临时表,现在可以接受性能