Reputation: 55
How can I find out the size occupied by Room databases by looking at the app settings? The storage section of the app settings is divided into Total, App size, User data and Cache. Does the app database account for the User data section or is it the Cache? 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.
Upvotes: 2
Views: 944
Reputation: 57033
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.
The number of rows doesn't exactly equate to database size. That is because the data is stored in pages (by default 4k). A table with 0 rows will take up 4k, with 1000 rows it could still just take up 4k.
Each SQLite entity (table, Index, Trigger etc) will take up at least 1 page.
You may wish to read SQLite Database File Format
Ignoring the page factor you could add a method to the @Database class like :-
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();
}
Working Example (based upon an existing App used for answering some qustions)
The @Database class :-
Retrieving the combined filesizes :-
@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();
}
}
and invoking code :-
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));
}
}
Result (i.e. the log includes) :-
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
Device Explorer shows :-
Explanation of the Results
As can be seen the result is showing that the database file itself is small in comparison to the -wal and -shm files (it is clear that WAL mode is in effect as both are greater than 0). This is because effectively the database consists of the -wal (i.e changes waiting to be applied to the database) and the database file. The -shm file will not be applied it is a work file used for the -wal file.
That is in WAL mode changes are written to the -wal file (roll back is removing part of the -wal file).
If journal mode were in effect then the journal is the log that is used to undo changes made to the database file.
Does the app database account for the User data section or is it the Cache?
Although you may wish to read:-
SQLite Temporary Files Used By SQLite
Additional
If you wanted to not have to pass the context when checking the size(s) then you could use something based upon :-
@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();
}
}
Upvotes: 1