13

Does an Android SQLite cursor load all data for a query into memory, or is there some sort of optimization strategy that's part of its implementation?

Julian A.
  • 10,928
  • 16
  • 67
  • 107
  • 1
    Just out of curiosity, why do you expect that SQLite cursors have a different default behaviour on Android compared to other platforms? – Lev Landau Jul 16 '15 at 21:52
  • @LevLandau: I don't have that expectation. But since I'm specifically interested in SQLite on Android, I made my question as narrow as possible. – Julian A. Jul 16 '15 at 21:54
  • 2
    Take a look at [this](https://groups.google.com/forum/#!topic/android-developers/QX0pI5bth8I) – GVillani82 Jul 16 '15 at 21:56
  • Cursor is temporary storage.It store data for some while .It directly load in memory.we can not optimize after loading in memory – Saveen Jul 16 '15 at 22:24
  • @LevLandau Android used `SQLite` library (C/C++ library). But SQLite publishes many methods for customize. So maybe Android platform will be different from others. For example, as my research, in Android, windows size of cursor is about 2MB. But maybe different at other platform. – hqt Jan 26 '16 at 11:45

3 Answers3

13

A SQLiteCursor fills a "window" with data as you navigate through it. My recollection is that the window size is 1MB, but I can't point you to specific code that backs up that recollection. So, for small queries, the net effect is that the SQLiteCursor will hold the entire result set in memory, once you start accessing rows and columns.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 2
    In SDK 23.0.1. It's 2MB. Please view my answer – hqt Jan 26 '16 at 11:37
  • 2
    What happens after the memory limit? Does the cursor need to go back and do a database read from the UI thread to get more data? – whizzle Feb 22 '16 at 19:05
  • 1
    @whizzle: Presumably. – CommonsWare Feb 22 '16 at 19:07
  • It looks like the source code confirms the `SQLiteCursor` fills a window: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/database/sqlite/SQLiteCursor.java – seadowg Mar 08 '21 at 11:22
13

Thanks for CommonsWare about Window term so I reversed again Android by navigating those classes SQLiteCursor -> AbstractWindowedCursor -> CursorWindow . Here is CursorWindow constructor:

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

As you can see, sCursorWindowSize is the size that CommonsWare has mentioned:

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

As my current version is Android SDK 23.0.1, the value of com.android.internal.R.integer.config_cursorWindowSize is 2048. It means 2MB. I don't have another version SDK for checking.

Community
  • 1
  • 1
hqt
  • 29,632
  • 51
  • 171
  • 250
  • It's defined as 2048 as far back as Android 4.0 which is as far as anyone supports I believe https://github.com/aosp-mirror/platform_frameworks_base/blob/fd1d05a01a704db47f6e60425c0ac3e1bd4cffbf/core/res/res/values/config.xml#L617 – Mike Hardy Apr 25 '21 at 16:54
4

Cursor doesn't contain all the results in memory but it does have the total count of the returned query (via getCount). While you iterate over the results it fetches the entries (not one by one I guess but probably in chunks). I'm pretty sure there are optimizations on this level. Once you're done with it you must close it - otherwise why would the system keep it open after the query has been already made.

MarkySmarky
  • 1,609
  • 14
  • 17