【问题标题】:Checking the size of Room database in device settings在设备设置中检查 Room 数据库的大小
【发布时间】:2021-09-05 12:20:50
【问题描述】:

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

【问题讨论】:

    标签: android database sqlite storage android-room


    【解决方案1】:

    我想估算一下我的数据库有多大,这样我就可以在不占用太多空间的情况下找到我可以在数据库中保留的最大行数。

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

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

    您不妨阅读SQLite Database File Format

    忽略页面因素,您可以向@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 文件的工作文件。

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

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

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

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

    尽管您可能希望阅读:-

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

    【讨论】:

      猜你喜欢
      • 2013-08-06
      • 1970-01-01
      • 2017-08-24
      • 1970-01-01
      • 2013-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多