Android SQLite选择查询速度

时间:2012-11-07 21:16:39

标签: android sqlite optimization select

我想帮助加快SQLite数据库中一个相当简单的选择查询。

查询正在搜索大约6500行的表,并且当前返回大约600ms。我不知道这是否可以接受,但我曾希望它会比那更快。我最终将这个放入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时间:588ms

感激不尽的任何帮助!

P.S这可能都不是问题 - 是一个可以接受查询的时间和6000个ArrayList的值吗?

2 个答案:

答案 0 :(得分: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 + "%'

答案 1 :(得分:0)

不要使用子查询;它没有做任何更快的事情,因为它仍然必须进行相同的检查。

不要使用LENGTH(column) >= value因为它不比LIKE检查快,也无法编入索引。

要加快LIKE,请在KEY_ID列上添加索引。 由于LIKE默认情况下不区分大小写,因此在创建索引时必须使用COLLATE NOCASE (见CREATE INDEX documentation)。