减小 Realm 文件大小 - Flutter SDK
Realm 的大小始终大于其中存储的对象的总大小。 这种架构实现了 Realm 的部分性能、并发性和安全优势。
Realm 会在文件中跟踪的未使用空间内写入新数据。 在某些情况下,未使用空间可能占 Realm 文件的很大一部分。 Realm的默认行为是自动压缩Realm以防止其变得太大。当自动压实不足以满足您的使用案例时,您可以使用手动压实策略。
自动压缩
版本 0.9.0 中的新增内容。
SDK 通过不断重新分配文件内的数据并删除未使用的文件空间,在后台自动压缩 Realm 文件。对于大多数应用程序来说,自动压缩足以最大限度地减小 Realm 文件。
当文件中未使用空间的大小超过文件中用户数据大小的两倍时,即会开始执行自动压缩。仅当文件未被访问时才会执行自动压缩操作。
手动压实策略
如果认为自动压实不够,对于需要更严格管理文件大小以提高性能的应用程序,可以使用手动压实。如果生产应用程序不使用自动压缩,则应实施手动压缩以定期减小 Realm 文件的大小。
压缩 Realm 可能是一项成本高昂的操作,可能会阻塞用户界面线程。 优化压缩以平衡频率与性能提升。 如果应用程序在资源有限的环境中运行,则可能需要在文件大小达到一定大小或文件大小对性能产生负面影响时进行压缩。
使用以下两种策略之一手动压缩 Realm 文件:
Realm.compact()静态方法:使用此方法可压缩 Realm。 您可以使用它来压缩 Flexible Sync Realm。
打开时有条件地压缩:如果要定义一个或多个条件来确定是否压缩域,请使用
shouldCompactCallback()
。 您可以检查特定域文件大小、未使用空间的百分比或与性能需求或运行时环境相关的其他条件。
Realm.compact() 静态方法
您可以通过调用 Realm .compact() 来压缩域文件 。此方法需要一个 配置 作为参数。使用此方法时,设备必须有足够的可用空间来创建域的副本。
Realm.compact()
获取 域 的实例,并将其打开以trigger任何模式版本升级、文件格式升级、迁移和初始数据回调。成功打开 Realm 并执行这些操作后,此方法会压缩 Realm。
如果成功,调用Realm.compact()
会返回true
。
请勿从事务内部调用此方法。 您也无法压缩开放 Realm。
final config = Configuration.local([Car.schema]); final compacted = Realm.compact(config); print( "Successfully compacted the realm: $compacted"); // On success, this prints "true" final realm = Realm(config);
打开时有条件地压缩
您可以定义一个 shouldCompactCallback() 作为 Realm 配置的属性。您可以将其与仅本地 Realm 和同步 Realm 一起使用,方法是 Configuration.local() 和 Configuration.FlexibleSync() 方法。
此回调采用两个int
值,分别代表磁盘上 Realm 文件的字节总数和已用字节数。 该回调会返回一个bool
。 仅当bool
返回true
并且其他进程当前未访问 Realm 文件时才会发生压缩。
最基本的用法是定义应进行压实的文件大小。
final config = Configuration.local([Car.schema], shouldCompactCallback: ((totalSize, usedSize) { // shouldCompactCallback sizes are in bytes. // For convenience, this example defines a const // representing a byte to MB conversion for compaction // at an arbitrary 10MB file size. const tenMB = 10 * 1048576; return totalSize > tenMB; })); final realm = Realm(config);
如果需要针对不同使用案例优化性能,您可以定义更复杂的逻辑。 例如,您可以设置压实阈值,以在文件大小的使用达到一定百分比时进行压实。
final config = Configuration.local([Car.schema], shouldCompactCallback: ((totalSize, usedSize) { // Compact if the file is over 10MB in size and less than 50% 'used' const tenMB = 10 * 1048576; return (totalSize > tenMB) && (usedSize.toDouble() / totalSize.toDouble()) < 0.5; })); final realm = Realm(config);