Android数据持久化方案调研-MMKV SP REALM ROOM WCDB...

官方方案对比

SharedPreference

简称SP,使用键值对的形式保存原始类型的数据,默认以XML格式的文件来存储这些数据java

  • 适用场景:存储量小、简单的数据
  • 优缺点:有本身的内存级的缓存,在数据量小的时候读取较快,可是跨进程不安全,数据量大的时候加载缓慢,全量写入,容易引发ANR

SQLite

  • 适用场景:比较复杂数据类型而且较大的数据量,成千上万的级别
  • 优缺点:相比SP来讲,须要在数据量较大的时候才有优点,数据的获取较慢,大量写入须要注意使用事务批处理,性能较高,若是频繁的单次插入性能不高,直接经过sql操做比较繁琐,能够考虑orm框架

File

  • 适用场景:顾名思义比较适用于文件类型的存储,如图片或者存储一些简单的文本数据或二进制数据
  • 优缺点:最基本的存储方式,它不对存储的内容进行任何的格式化处理,全部数据都是原封不动地保存到文件当中的

小结

因为咱们目前使用的SP方案,咱们的痛点,性能差,和ANR问题,考虑换一种数据存储方案,首先咱们的数据存储的场景并非复杂数据类型,量上也不是太大,因此优先考虑的就是MMKV,为了更清楚的了解MMKV的优缺点,因此对比参考下android

开源方案对比

各类方案简介

名称 MMKV Realm WCDB Room
方案 mmap nosql SQLCipher SQLite
版本 1.0.24 6.0.2 1.0.8 2.2.3
size 0.15mb 1.5mb 0.7mb 0.05mb
迁移 从SP迁移方便 从SQLite迁移方便
场景 替换SP 替换SQLite 替换SQLite 替换SQLite

注: size 为armeabi-v7a架构下打包增量大小
mmkv包含lib_c++shared库的size为0.3mbc++

性能对比

初始化

初始化 MMKV SP Realm Room WCDB
耗时 30ms 4ms 60ms 15ms 80ms
内存 1mb 约1mb 约2mb 1mb 2mb
cpu峰值 16% 20% 18% 15% 15%

读写速度和数据文件大小等数据对比

SP 执行次数 写入耗时 读取耗时 数据文件
字符串 200 51ms 4ms 8kb
字符串 1000 171ms 6ms 42kb
Java实体 1000 220ms 87ms 172kb
MMKV 执行次数 写入耗时 读取耗时 数据文件
字符串 200 8ms 5ms 4kb
字符串 1000 20ms 9ms 16kb
Java实体 1000 117ms 93ms 128kb
Realm 执行次数 写入耗时 读取耗时 数据文件
字符串 200 229ms 74ms 32kb
字符串 1000 606ms 122ms 288kb
Java实体 1000 760ms 130ms 576kb
Room 执行次数 写入耗时 读取耗时 数据文件
字符串 200 636ms 160ms 32kb
字符串 1000 1350ms 475ms 48kb
Java实体 1000 1298ms 432ms 68kb
wcdb 执行次数 写入耗时 读取耗时 数据文件
字符串 200 636ms 160ms 32kb
字符串 1000 1350ms 475ms 48kb
Java实体 1000 1298ms 432ms 68kb

内存消耗

内存消耗 MMKV SP
初始化 + 查询1k条 1.7mb 1.2mb
初始化 + 查询1w条 3.6mb 2.8mb
初始化 + 查询5w条 10.7mb(文件8mb) 8.5mb(文件8.6mb)

指标备注

字符串数据:含有随机数的10个字节
运行手机:华为 Mate10
执行线程:子线程
统计方式:取3次平均值
内存消耗:业务代码读取对应数据后释放本地对象后的内存增量
因为序列化反序列化会有缓存,Java实体
SP写入为apply异步方式
Realm、WCDB、Room 的插入操做均为单条插入
MMKV、SP 读取和写入Java实体对象数据时间包含实体类序列化和反序列化时间,不过因为序列化反序列化会有缓存,时间会稍偏小git

测试整理

  • 初始化性能,cpu峰值和内存增加都相差无几,耗时来看,因为SP和Room都是系统原生的方案,耗时较短。
  • MMKV和SP新增了内存消耗一项,主要是由于本身有一分内存级别的缓存,须要验证下对内存的影响,从测试数据来看,这两个方案内存增加至关,能够接受。
  • MMKV使用protobuf存储,SP使用xmlprotobuf相比xml来讲性能更好,体积也会减少,可是真实存储空间来看,mmkv的扩容机制(在空间不足时会申请一倍的空间)可能会致使实际使用空间变大,相比较SP的占用的存储空间就是真实的数据大小。

开源方案总结

MMKV

MMKV 经过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由操做系统负责将内存回写到文件,没必要担忧 crash 致使数据丢失。而SP则 MMKV 是一个跨平台的解决方案,写入性能相比sp有很大提高,适用于须要一个通用的 key-value 存储组件,有跨进程访问需求,尤为是对如今sp存储方案的不满的同窗,mmkv同时支持了sp的迁移支持,基本上不用调整太多的代码,迁移事项下面会详述。github

Realm

Realm做为一款移动端的NoSQL框架,官方定位就是替代SQLite等关系型数据库,跨平台,性能优秀,有可视化的查看工具。不足也比较明显,不管是集成包size仍是数据文件都有点大。另外Realm要求当前Bean对象必须直接继承RealmObject,侵入性很是强。有线程限制,不能跨线程使用数据对象。另外我在写测试demo的时候发现了一个坑,若是一个线程查询出列表后,另外一个线程再去增长或删除会使得本地数据文件产生备份,致使数据库文件急速增加,达到几百MB,而且不会自动清理,官方对这个也有说明:sql

WCDB

WCDB是一个高效、完整、易用的移动数据库框架,基于SQLCipher,支持iOS, macOS和Android数据库

Room

Room并非一个数据库,他是在 SQLiteo 的基础上提供了一个抽象层,让用户可以在充分利用 SQLite 的强大功能的同时,获享更强健的数据库访问机制。并保留了灵活的接口适配层。目前WCDB已经支持接入Room:github.com/Tencent/wcd…缓存

ObjectBox

想尝试的同窗能够试试 ObjectBox,这个也是GreenDao做者的另外一力做,听说性能比Realm还要好,因为本次是对老项目中的SP存储方案选型替换,暂时先不对比ObjectBox了,后续有时间了完善下相关对比记录,有几篇文章你们能够参考
notes.devlabs.bg/realm-objec…
chejdj.github.io/android/201…安全

综述

总结下吧,sp 和 mmkv 都是本身有一分内存级别的缓存,因此查询很是快,可是若是数据量过大,会形成内存溢出,mmkv官方也对这点有说明,不要超过100mb,其实对正常的数据来讲,确定到不了这个限制,若是30mb以上的数据,都要考虑使用数据库类型的存储了,上面测试数据对于数据库类型的存储不太公平,主要针对单次频繁插入查询的使用场景,数据库使用场景通常会多条数据经过事务批量写入,查询的时候也会查询一类数据集合。综上所述,目前采用mmkv替换sp的实现仍是有很大收益的,性能和跨进程上都有优点,而且避免了sp的ANR问题,体积上也没有加大多少;若是数据库方案,建议采用Room,或者在尝试下上面说的可是没在本次测试对比的objectbox。感受要注意的挺多,不过零零散散只整理了这么点...架构

MMKV迁移参考

  • 迁移官方文档:github.com/Tencent/MMK…

  • MMKV 不支持 Serializable,可是能够考虑把 Serializable 的 java对象 转换成 byte 存入MMKV

  • MMKV初始存储空间4kb,不足的时扩容最少是一倍,而且为了效率在移除key value不会减少磁盘存储空间,官方提供了kv.trim方法去缩减磁盘存储空间,不过官方建议调用时机是有大量移除操做的时候执行,通常无需考虑存储文件增加问题,但这个时机很差掌握,不过感受能够按期清理一次

  • SP#getAll SP#registerOnSharedPreferenceChangeListener 等方法不支持,调用会抛出运行时异常,须要注意。getAll由于擦除了类型,因此不支持,感受这是mmkv相对较弱的地方,也为之后迁移其余存储方案增长了成本

  • 一些 Android 设备(API level 19)在安装/更新 APK 时可能出错, 致使 libmmkv.so 找不到。而后就会遇到 java.lang.UnsatisfiedLinkError 之类的 crash。有个开源库 ReLinker 专门解决这个问题,不过如今还在支持19的应用应该很少了

  • 对于历史项目SP数据可能比较庞大,这样直接使用官方提供的mmkv#importFromSharedPreferences方法直接对一个文件进行迁移,会形成耗时过长的问题,目前Demo测试数据:测试机型华为Mate10,一个4MB左右的SP的文件迁移到MMKV大约耗时80ms左右,到了线上应该还会更长,因此为了不初次使用卡住的体验问题,这里提供两个解决思路:1.在使用前统一迁移,而且给予用户一个迁移数据的提示;2.在初次使用的时候后台静默迁移。目前咱们使用的是第二种思路,这种状况须要保证数据的准确性,若是有同窗有兴趣能够留言探讨

参考

官方和网上各类对比测试文章

相关文章
相关标签/搜索