Android SQLite游标一次性加载所有记录到内存中吗?

13

Android SQLite游标是否会将查询的所有数据加载到内存中,还是其实现中有某种优化策略?


1
只是出于好奇,为什么你认为在Android上,SQLite游标的默认行为与其他平台不同呢? - Lev Landau
@LevLandau:我并没有那样的期望。但是由于我特别关注Android上的SQLite,所以我把我的问题尽可能地缩小了范围。 - Julian A.
2
请看这个链接 - GVillani82
游标是临时存储,它可以暂存数据。它会直接加载到内存中,加载后无法优化。 - Saveen
@LevLandau Android使用了SQLite库(C/C++库)。但是SQLite发布了许多自定义方法。因此,Android平台可能与其他平台不同。例如,根据我的研究,在Android中,游标的窗口大小约为2MB。但在其他平台上可能会有所不同。 - hqt
3个回答

13

感谢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);
    }

正如你所看到的,sCursorWindowSizeCommonsWare 提到的大小:

sCursorWindowSize = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_cursorWindowSize) * 1024;

由于我目前的版本是Android SDK 23.0.1com.android.internal.R.integer.config_cursorWindowSize的值为2048。这意味着2MB。我没有其他版本的SDK进行检查。


据我所知,它被定义为2048,甚至在Android 4.0时就已经如此,这也是任何人支持的范围之内。请参见此链接:https://github.com/aosp-mirror/platform_frameworks_base/blob/fd1d05a01a704db47f6e60425c0ac3e1bd4cffbf/core/res/res/values/config.xml#L617 - Mike Hardy

13

SQLiteCursor 填充一个“窗口”,随着您浏览它而填充数据。我记得窗口大小是1MB,但我无法指向支持该记忆的特定代码。因此,对于小查询,SQLiteCursor 的净效果是,一旦您开始访问行和列,它将在内存中保存整个结果集。


2
在SDK 23.0.1中,它的大小为2MB。请查看我的答案。 - hqt
2
内存限制后会发生什么?光标需要返回并从UI线程读取数据库以获取更多数据吗? - whizzle
1
@whizzle:大概吧。 - CommonsWare
看起来源代码确认了 SQLiteCursor 填充了一个窗口:https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/database/sqlite/SQLiteCursor.java - seadowg

4

游标(Cursor)并没有将所有结果保存在内存中,但是它通过 getCount 方法返回了查询结果的总数。当您遍历结果时,它会获取条目(我猜不是一条一条获取,而是按块获取)。我相信这个层面上进行了优化。用完后必须关闭游标,否则在查询完成后为何系统要保持其开启。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接