首页 > 解决方案 > 在设备设置中检查 Room 数据库的大小

问题描述

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

标签: androiddatabasesqlitestorageandroid-room

解决方案


我想估计我的数据库有多大,这样我就可以找到我可以在数据库中保留的最大行数,而不会占用太多空间。

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

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

您可能希望阅读SQLite 数据库文件格式

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

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 类:-

检索组合的文件大小:-

@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();
    }
}
  • 注意为演示/解释添加的单个文件大小

并调用代码:-

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 文件的一部分)。

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

应用程序数据库是用户数据部分还是缓存?

尽管您可能希望阅读:-

SQLite 预写式日志记录

SQLite 使用的 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();
    }
}

推荐阅读