-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Java|Kotlin 数据压缩
用户使用应用的时间越多,其相关的数据库一般也越大。过大的数据库不仅会占用磁盘空间,而且还会给数据备份和读写等操作带来性能压力。终端数据库的内容中,占用空间大的主要是各种xml、json之类的序列化内容。我们在实际的业务场景中,一个xml长达10k的情况比比皆是。
解决数据库内容过大的直接方法,就是先将数据压缩一下再写入数据库,这样开发者就需要解决下面三个问题:
- 选择一个合适的压缩算法。
- 在所有读写环节都需要引入数据的加解压逻辑。
- 压缩存量数据。
为了解决上面提到的数据压缩时会遇到的共性问题,WCDB引入了数据压缩能力。开发者可以使用简单的配置就可以实现数据压缩了。
首先 WCDB 使用的压缩组件是 Zstd,Zstd采用的压缩算法是[ANS+FSE][]算法,是现在已知压缩率和加解压性能综合最优的算法,而且Zstd还实现了字典压缩模式,可以更好得压缩xml或json中公共标签这部分内容,进一步提高压缩率和性能。WCDB把Zstd的普通压缩和字段压缩都支持了,还支持根据某个字段的不同值使用不同的字典来压缩。下面是不同模式的配置示例:
database.setCompression(new Database.CompressionFilter() {
@Override
public void filterCompress(Database.CompressionInfo info) {
// 数据库中的每个表都会回调,先判断表名
if(info.table.equals("sampleTable")){
// 1. 使用Zstd的默认压缩方式来压缩表中的 content 字段
info.addZSTDNormalCompress(DBSample.content);
// 2. 配置使用注册的字典来压缩 content 字段
// 字典需要使用 trainDictWithString 或 trainDictWithData 来训练,并使用 registerDict 方法来提前注册
info.addZSTDDictCompress(DBSample.content, dictId);
// 3. 配置使用多种字典来压缩 content 字段
// 其中 id 字段为 0 时使用 dictId1 对应的字典,为 1 时使用 dictId2,其他情况使用 dictId3。
info.addZSTDMultiDictCompress(DBSample.content, DBSample.id, new HashMap<long, byte>(){{
put(0, dictId1);
put(1, dictId2);
put(Database.DictDefaultMatchValue, dictId3);
}});
}
}
});
以上代码都可以用 Kotlin 实现,因为篇幅限制,就不单独演示了,下同。
配置好之后,开发就不用关注数据加解压的实现细节了,可以照常使用这些配置了压缩的表。WCDB会自动把新写入的数据按照配置的压缩方式来压缩,读数据的时候也会自动把数据解压了之后在给出来,对原有的读写逻辑无侵入。
对于存量数据,开发者如果也要压缩,可以使用enableAutoCompression
方法来开启 WCDB 自动压缩逻辑逻辑。WCDB 会每隔 2 秒压缩 100 条存量数据,而且这个处理通过锁监控机制,会避免影响到数据库的写性能。开发者也可以使用stepCompression()
接口手动压缩存量数据,自己控制数据压缩的节奏。可以使用setNotificationWhenCompressed(CompressionNotification)
接口注册压缩进度的监听,每次迁移完一个存量表格都会回调。下面是压缩过程的使用示例:
assert !database.isCompressed();
final String[] compressedTable = {null};
database.setNotificationWhenCompressed(new Database.CompressionNotification() {
@Override
// 每压缩完一个存量表格都会回调
// 当前数据库的全部存量表格都压缩完时还会额外回调一次,这次的tableName参数就会为null或空字符串
public void onCompressed(Database database, String tableName) {
if(tableName != null && !tableName.empty()){
compressedTable[0] = tableName;
}
}
});
while(!database.isCompressed()) {
database.stepCompression();
}
assert compressedTable[0].equals("sampleTable");
同时,数据压缩可以和数据迁移可以一起配置到同一个表的,两个操作将会独立生效,互不干扰,可以实现一边迁表或拆表,一边压缩目标表的效果,这些复杂玩法就交给开发者去探索了。
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程