在设备设置中检查 Room 数据库的大小

Checking the size of Room database in device settings

如何通过查看应用程序设置了解 Room 数据库占用的大小?应用程序设置的存储部分分为总计、应用程序大小、用户数据和缓存。应用程序数据库占用户数据部分还是缓存?我想估计我的数据库有多大,这样我就可以找到我可以在数据库中保留的最大行数,而不会占用太多 space.

I want to find an estimate of how big my database is so I can find the maximum number of rows I can keep in the db without it taking too much space.

行数并不完全等于数据库大小。这是因为数据存储在页面中(默认为 4k)。 table 0 行将占用 4k,1000 行它仍然可能只占用 4k。

每个 SQLite 实体(table、索引、触发器等)将至少占用一页。

您不妨阅读SQLite Database File Format

忽略页面因素,您可以向@Database class 添加一个方法,例如:-

public static long getDBSize(Context context) {

    return (context.getDatabasePath(instance.getOpenHelper().getDatabaseName())).length()
            // Add the shared memory (WAL index) file size
            + (context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-shm")).length()
            // Add the WAL file size
            + (context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-wal")).length()
            // Add the journal file size
            + (context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-journal")).length();
}

工作示例 (基于用于回答一些问题的现有应用程序)

@Database class :-

正在检索组合文件大小 :-

@Database(entities = {State.class,Location.class,School.class,TimerDesign.class,IntervalDesign.class,Table1.class, MessageItem.class, Contact.class},exportSchema = false,version = 1)
abstract class TheDatabase extends RoomDatabase {
    abstract AllDao getAllDao();

    private static volatile TheDatabase instance;
    public static TheDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(
                    context,
                    TheDatabase.class,
                    "state.db"
            )
                    .allowMainThreadQueries()
                    .addCallback(new Callback() {
                        @Override
                        public void onCreate(SupportSQLiteDatabase db) {
                            super.onCreate(db);
                        }

                        @Override
                        public void onOpen(SupportSQLiteDatabase db) {
                            super.onOpen(db);
                        }
                    })
                    .build();
        }
        return instance;
    }
    public static long getDBSize(Context context) {

        // For Demonstration Log the individual sizes
        Log.d("DBSIZEINFO",
                "Space from main DB file = " + String.valueOf(context.getDatabasePath(instance.getOpenHelper().getDatabaseName()).length())
                + "\nSpace from -shm file = " + String.valueOf(context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-shm").length())
                + "\nSpace from -wal file = " + String.valueOf(context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-wal").length())
                + "\nSpace from journal file = " + String.valueOf(context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-journal").length())
        );

        return (context.getDatabasePath(instance.getOpenHelper().getDatabaseName())).length()
                // Add the shared memory (WAL index) file size
                + (context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-shm")).length()
                // Add the WAL file size
                + (context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-wal")).length()
                // Add the journal file size
                + (context.getDatabasePath(instance.getOpenHelper().getDatabaseName() + "-journal")).length();
    }
}
  • 注意为 demo/explanation
  • 添加的单个文件大小

并调用代码:-

public class MainActivity extends AppCompatActivity {

    TheDatabase db;
    AllDao dao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Instantiate Database and get dao
        db = TheDatabase.getInstance(this);
        dao = db.getAllDao();
        Log.d("DBSIZEINFO","Database Size is " + TheDatabase.getDBSize(this));
    }
}

结果(即日志包括):-

2021-06-22 09:20:53.960 25867-25867/a.a.so67952337javaroomstatefacilities D/DBSIZEINFO: Space from main DB file = 4096
    Space from -shm file = 32768
    Space from -wal file = 70072
    Space from journal file = 0
2021-06-22 09:20:53.960 25867-25867/a.a.so67952337javaroomstatefacilities D/DBSIZEINFO: Database Size is 106936

设备资源管理器显示:-

结果说明

可以看出,结果显示数据库文件本身与 -wal 和 -shm 文件相比较小(很明显 WAL 模式有效,因为两者都大于 0)。这是因为实际上数据库由 -wal(即等待应用到数据库的更改)和数据库文件组成。 -shm 文件将不会应用它是用于 -wal 文件的工作文件。

  • -wal 文件在进行 CHECKPOINTS 时应用(可能是部分应用)。

在 WAL 模式下,更改将写入 -wal 文件(回滚是删除部分 -wal 文件)。

如果日志模式有效,则日志是用于撤消对数据库文件所做更改的日志。

Does the app database account for the User data section or is it the Cache?

尽管您可能希望阅读:-

SQLite Write-Ahead Logging

SQLite Temporary Files Used By SQLite

额外

如果您不想在检查尺寸时传递上下文,那么您可以使用基于 :-

的东西
@Database(entities = {State.class,Location.class,School.class,TimerDesign.class,IntervalDesign.class,Table1.class, MessageItem.class, Contact.class},exportSchema = false,version = 1)
abstract class TheDatabase extends RoomDatabase {
    abstract AllDao getAllDao();

    private static volatile TheDatabase instance;
    private static File databaseFile; //<<<<<<<<<< ADDED
    public static TheDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(
                    context,
                    TheDatabase.class,
                    "state.db"
            )
                    .allowMainThreadQueries()
                    .addCallback(new Callback() {
                        @Override
                        public void onCreate(SupportSQLiteDatabase db) {
                            super.onCreate(db);
                        }

                        @Override
                        public void onOpen(SupportSQLiteDatabase db) {
                            super.onOpen(db);
                        }
                    })
                    .build();
        }
        databaseFile = context.getDatabasePath(instance.getOpenHelper().getDatabaseName()); //<<<<<<<<<< ADDED
        return instance;
    }

    /* ALTERNATIVE without the need for the Context*/
    public static long getDBSize() {
        if (databaseFile == null) return -1;
        return databaseFile.length() +
                new File(databaseFile.getPath() + "-shm").length() +
                new File(databaseFile.getPath() + "-wal").length() +
                new File(databaseFile.getPath() + "-journal").length();
    }
}