【问题标题】:Inserting into db while iterating through cursor遍历游标时插入数据库
【发布时间】:2014-05-26 03:33:17
【问题描述】:

我有一个游标,其中包含来自我的数据库的 3 列。我需要遍历并将 ID 添加到另一个表中。我尝试使用下面的代码,但它导致了“应用程序没有响应”消息,并且需要大约 10 秒来插入所有行(大约 1000 行)。

我已经更改了代码,以便遍历游标并分别插入到数据库中,现在这大约需要 500 毫秒。虽然看起来我已经解决了我的问题,但我不明白为什么。

谁能解释一下为什么下面的代码需要这么长时间才能执行?

public void setNowPlayingSongs(SQLiteDatabase db, Cursor cursor) {
    // Clear all the current songs
    db.delete(TABLE_NOW_PLAYING, null, null);

    ContentValues cv = new ContentValues();
    cursor.moveToFirst();

    int index = cursor.getColumnIndex(COL_ID);

    while (!cursor.isAfterLast()){
        cv.put(COL_SONG_ID, cursor.getInt(index));
        db.insert(TABLE_NOW_PLAYING, null, cv);
        cursor.moveToNext();
    }

}

为什么这要快得多?我不明白为什么遍历光标然后遍历列表会更快。我认为上面的方法应该更快?

public void setNowPlayingSongs(SQLiteDatabase db, Cursor cursor) {
    ContentValues cv;
    List<Integer> ids;
    int index;

    // Clear all the current songs
    db.delete(TABLE_NOW_PLAYING, null, null);

    // Check which column holds the IDs
    index = cursor.getColumnIndex(COL_ID);

    // Add the ids to a list
    ids = new ArrayList<Integer>();
    cursor.moveToFirst();        
    while (!cursor.isAfterLast()) {
        ids.add(cursor.getInt(index));
        cursor.moveToNext();
    }

    // Insert the IDs into the now playing table.
    cv = new ContentValues();
    db.beginTransaction();
    for (Integer id : ids) {
        cv.put(COL_SONG_ID, id);
        db.insert(TABLE_NOW_PLAYING, null, cv);
    }
    db.setTransactionSuccessful();
    db.endTransaction();
}

【问题讨论】:

    标签: android database sqlite insert android-cursor


    【解决方案1】:

    当您执行单独的插入时,每个插入实际上都包含在 SQLite 事务中。如果您改为在单个事务中执行所有插入,这应该会大大加快速度。

    db.beginTransaction();
    try {
        // do your inserts
    
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
    

    【讨论】:

    • 我确实这样做了,虽然它加快了速度,但仍然需要大约 6 或 7 秒。唯一真正有效的方法是先遍历光标(将 id 添加到列表中),然后遍历列表进行 db 插入,但我不明白为什么要遍历 1000 个 id twice 比我原来的方法快
    • 使用原始插入语句将大大提高性能@karakuri
    • @arul 你说得对。您可以通过使用SQLiteStatement 并在每次迭代中绑定新值来加快速度。通常SQLiteDatabase 必须准备语句并绑定参数,因此您不必一遍又一遍地准备相同的语句来节省。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多