0

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

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

  • 书:int
  • 章节:int
  • 诗句:诠释
  • wordIdx : 整数
  • 强ID:字符串
  • 词:字符串

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

所以我有 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 秒。

我怎样才能提高这个性能?似乎临时视图对性能没有我希望的影响。

4

2 回答 2

1

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

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

如果没有任何索引,您的查询总是会扫描整个表:

> 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 检查实际使用了哪些索引,以及是否可以创建一些索引来优化大多数查询。

另请参阅查询计划文档。

于 2013-02-06T11:49:55.647 回答
0

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

于 2013-02-21T22:37:39.263 回答