Android SQLite游标是否会将查询的所有数据加载到内存中,还是其实现中有某种优化策略?
感谢CommonsWare关于术语Window
的解释,我通过浏览这些类SQLiteCursor -> AbstractWindowedCursor -> CursorWindow
又一次逆向了Android。这是CursorWindow
构造函数:
public CursorWindow(String name) {
mStartPos = 0;
mName = name != null && name.length() != 0 ? name : "<unnamed>";
if (sCursorWindowSize < 0) {
/** The cursor window size. resource xml file specifies the value in kB.
* convert it to bytes here by multiplying with 1024.
*/
sCursorWindowSize = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_cursorWindowSize) * 1024;
}
mWindowPtr = nativeCreate(mName, sCursorWindowSize);
if (mWindowPtr == 0) {
throw new CursorWindowAllocationException("Cursor window allocation of " +
(sCursorWindowSize / 1024) + " kb failed. " + printStats());
}
mCloseGuard.open("close");
recordNewWindow(Binder.getCallingPid(), mWindowPtr);
}
正如你所看到的,sCursorWindowSize
是 CommonsWare 提到的大小:
sCursorWindowSize = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_cursorWindowSize) * 1024;
由于我目前的版本是Android SDK 23.0.1
,com.android.internal.R.integer.config_cursorWindowSize
的值为2048。这意味着2MB。我没有其他版本的SDK进行检查。
SQLiteCursor
填充一个“窗口”,随着您浏览它而填充数据。我记得窗口大小是1MB,但我无法指向支持该记忆的特定代码。因此,对于小查询,SQLiteCursor
的净效果是,一旦您开始访问行和列,它将在内存中保存整个结果集。
SQLiteCursor
填充了一个窗口:https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/database/sqlite/SQLiteCursor.java - seadowg游标(Cursor)并没有将所有结果保存在内存中,但是它通过 getCount 方法返回了查询结果的总数。当您遍历结果时,它会获取条目(我猜不是一条一条获取,而是按块获取)。我相信这个层面上进行了优化。用完后必须关闭游标,否则在查询完成后为何系统要保持其开启。
SQLite
库(C/C++库)。但是SQLite发布了许多自定义方法。因此,Android平台可能与其他平台不同。例如,根据我的研究,在Android中,游标的窗口大小约为2MB。但在其他平台上可能会有所不同。 - hqt