android - 在设备设置中检查 Room 数据库的大小
问题描述
如何通过查看应用程序设置找出 Room 数据库占用的大小?应用设置的存储部分分为Total、App size、User data和Cache。应用程序数据库是用户数据部分还是缓存?我想估计我的数据库有多大,这样我就可以找到我可以在数据库中保留的最大行数,而不会占用太多空间。
解决方案
我想估计我的数据库有多大,这样我就可以找到我可以在数据库中保留的最大行数,而不会占用太多空间。
行数并不完全等于数据库大小。那是因为数据存储在页面中(默认为 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 文件的一部分)。
如果日志模式有效,则日志是用于撤消对数据库文件所做更改的日志。
应用程序数据库是用户数据部分还是缓存?
尽管您可能希望阅读:-
额外的
如果您不想在检查大小时传递上下文,那么您可以使用基于以下内容的内容:-
@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();
}
}
推荐阅读
- javascript - 单击与另一个按钮同名的带有 javascript 的按钮
- python - Python bar-chart-race TypeError: bar_chart_race() got an unexpected keyword argument 'img_label_folder'
- javascript - 谷歌文档应用程序脚本函数调用非常慢
- javascript - 电子“TypeError [ERR_INVALID_ARG_VALUE] 参数‘args’无效”
- amazon-web-services - CodeBuild 无法在 docker build 中从 S3 提取文件
- r - 检查函数 r 中的参数
- php - TinyMCE 图像上传未在一个页面中使用多个编辑器设置“src”属性
- ios - 用于在 Azure B2C 中注册的应用程序平台中 iOS Bundle ID 的正则表达式
- c++ - 使用 QAxWidget 获取 Webview2 按键
- python - python类:通过列表访问时类属性不会更新