3

SQLiteデータベース でかなり単純な選択クエリを高速化する方法を教えてください。

クエリは約 6500 行のテーブルを検索しており、現在約 600 ミリ秒で返されます。それが受け入れられるかどうかはわかりませんが、それよりも速いことを望んでいました。最終的にはこれを に入れますがAsyncTask、可能な限り最適化したかったのです。以下のコード スニペットで、私が試したことを確認できます。
KEY_songPath は索引付けされています。

public ArrayList<Song> getCurrentDirSongs(String currentDir) {
long startTime = System.currentTimeMillis();
ArrayList<Song> songsList = new ArrayList<Song>();

String selectQuery = "";
int strLength = currentDir.length();
    //selectQuery = "SELECT  * FROM " + TABLE_SONGS + " WHERE (" + KEY_songPath + " >= '" + currentDir + "')";
    //selectQuery = "SELECT  * FROM " + TABLE_SONGS + " WHERE (" + KEY_songPath + " GLOB '" + currentDir + "*')";
    //selectQuery = "SELECT  * FROM " + TABLE_SONGS + " WHERE (" + KEY_songPath + " LIKE '" + currentDir + "%')";
    selectQuery = "SELECT  * FROM " + TABLE_SONGS + " WHERE " + KEY_ID +
                    " IN (SELECT " + KEY_ID +" FROM "+ TABLE_SONGS + " WHERE length(" + KEY_songPath + ")>= "+ strLength +") AND " + 
                    "(" + KEY_songPath + " LIKE '" + currentDir + "%')";

SQLiteDatabase db = this.getReadableDatabase();

Cursor cursor = db.rawQuery(selectQuery, null);

// looping through all rows and adding to list
if (cursor.moveToFirst()) {
    do {
        Song song = new Song();
        song.setSongTitle(cursor.getString(1));
        song.setSongPath(cursor.getString(2));
        song.setSongArtist(cursor.getString(3));
        song.setSongAlbum(cursor.getString(4));
        song.setTrackNumber(cursor.getString(5));
        song.setID(Integer.parseInt(cursor.getString(6)));
        song.setAlbumID(Integer.parseInt(cursor.getString(7)));
        song.setArtistID(Integer.parseInt(cursor.getString(8)));
        song.setSongCheckedStatus(Boolean.parseBoolean(cursor.getString(9)));
        song.setSongPosition(Integer.parseInt(cursor.getString(10)));
        song.setSongDuration(Integer.parseInt(cursor.getString(11)));
        // Adding song to list
        songsList.add(song);
    } while (cursor.moveToNext());
}
long estimatedTime = System.currentTimeMillis() - startTime;
Log.d("AMCDatabase Database Handler: ", "SongsList.size(): "+ getSongsCount("SongsList") + " Time: " + estimatedTime + "ms");
// return contact list
return songsList;

}

これにより、次の結果が返されました: SongsList.size(): 6390 Time: 588ms

どんな助けでもありがたく受け取った!

PSこれはすべて問題ではないかもしれません.1秒間のクエリと6000の値は許容できますArrayListか?

4

2 に答える 2

0

ネストされたステートメントを使用しないようにしてください。SELECT代わりに、使用できるかどうかを確認してくださいJOIN

例:

SELECT * FROM Songs AS s1 JOIN Songs AS s2 ON s1.KEY_ID = s2.KEY_ID WHERE length (s2.KEY_SONGPATH) >= " + strLength + ") AND s1.KEY_SONGPATH LIKE '" + currentDir + "%'
于 2012-11-07T21:17:56.317 に答える
0

サブクエリを使用しないでください。同じチェックを行う必要があるため、何も高速化されません。

LENGTH(column) >= valueチェックよりも高速ではなくLIKE、インデックスを作成できないため、使用しないでください。

を高速化するLIKEには、列にインデックスを付けKEY_IDます。LIKEはデフォルトで大文字と小文字が区別されないためCOLLATE NOCASE、インデックスを作成するときに使用する必要があります ( CREATE INDEX のドキュメントを参照してください)。

于 2012-11-08T08:00:19.790 に答える