0

SQLiteDatabase を使用して Android で SQLite を使用しています ( http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html )

次の列を持つ単一のテーブルを持つ聖書アプリケーションを開発しています。

  • ブック : int
  • チャプター : int
  • 詩:int
  • wordIdx : int
  • strongId : 文字列
  • 単語 : 文字列

各文は一連の strongId/単語のペアに分割されるため、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 に削減されますが、クエリにはまだ時間がかかります。

ユーザーに表示する 2 つの章のテキストを生成するのに約 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)

3 つのルックアップ フィールドにインデックスを使用すると、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 は、クエリ内のテーブルごとに最大 1 つのインデックスを使用できるため、複数のインデックスを作成することは常に意味があるとは限らないことに注意してください。EXPLAIN QUERY PLAN を使用して、実際に使用されているインデックスと、ほとんどのクエリを最適化するためにいくつかのインデックスを作成できるかどうかを確認します。

クエリ計画のドキュメントも参照してください。

于 2013-02-06T11:49:55.647 に答える
0

一時テーブルを作成することになり、パフォーマンスは許容できるようになりました

于 2013-02-21T22:37:39.263 に答える