2

我在我的一个项目中使用了 Realm.io,我已经在几个 iOS 项目中使用过它,但这是我第一个使用它的 Objective C 桌面应用程序,所以这个问题是基于 OS X 的使用情况。在继续之前,我认为还值得一提的是测试机器正在运行 El Capitan,所以我知道这是测试版软件。

Realm 作为 CocoaPod 加载,一切正常,我可以运行查询等,启动没有问题或其他任何东西让我觉得我可能没有正确关闭我的电话?

我的对象有两种主要的不同类型,一种用于保存“组”,另一种用于保存实际的“对象”。该应用程序是一个照片上传器,因此它会读取 Apple 的照片应用程序,索引所有媒体对象和组,然后上传它们。

在第一次运行时,或者如果我完全删除了领域,所以我们从头开始,一切都会飞快地进行。在下一次运行中,我的查询似乎运行得更慢,数据库首先从 25Mb 变为 50Mb,然后在一个小时后我再次检查时,我的大小约为 11Gb。

我对 Realm 的主要用途是在单例中,但我正在执行一个后台队列,该队列正在为每个对象排队一个新作业,因此当它发现一张照片时,它会排队另一个作业以检查它是否存在于数据库中,如果不存在则创建它,如果是这样,它会更新任何现有信息。因为它这样做,除非我在作业中声明 Realm,否则我会得到线程错误,所以每次都定义它。

下面是我的一个电话示例,任何人都可以提出一些我可能做错的事情,或者无论如何控制或压缩数据库的大小,现在它这么大?

- (void)saveMediaObject:(MLMediaObject *)mediaObject mediaGroup:(MLMediaGroup *)mediaGroup
{
    [jobQueue addOperationWithBlock:
     ^{
         NSLog(@"saveMediaObject");

         lastScanResult = [NSDate date];

         RLMRealm *realm = [RLMRealm defaultRealm];

         SPMediaObject *spMediaObject = [SPMediaObject objectInRealm:realm forPrimaryKey:[mediaObject identifier]];

         if(spMediaObject == nil)
         {
             spMediaObject = [[SPMediaObject alloc] init];
             spMediaObject.identifier = [mediaObject identifier];
         }

         [realm beginWriteTransaction];

         spMediaObject.lastSeen = [NSDate date];
         spMediaObject.versionURL = [[mediaObject URL] path];
         spMediaObject.versionMimeType = [self mimeTypeForExtension:[[spMediaObject.versionURL pathExtension] lowercaseString]];
         spMediaObject.originalURL = [[mediaObject originalURL] path];
         spMediaObject.originalMimeType = [self mimeTypeForExtension:[[spMediaObject.originalURL pathExtension] lowercaseString]];

         if([mediaObject name] != nil)
         {
             spMediaObject.caption = [mediaObject name];
         }
         else
         {
             spMediaObject.caption = @"";
         }

         [realm addOrUpdateObject:spMediaObject];

         [realm commitWriteTransaction];
     }];
}

史蒂夫。

4

1 回答 1

2

Realm 关于文件大小的文档应该提供一些关于这里发生的事情以及如何缓解问题的见解:

您应该期望 Realm 数据库比等效的 SQLite 数据库占用更少的磁盘空间。如果您的 Realm 文件比您预期的要大得多,可能是因为您有一个RLMRealm引用数据库中旧版本数据的文件。

为了给您提供一致的数据视图,Realm 仅更新在运行循环迭代开始时访问的活动版本。这意味着如果您从 Realm 读取一些数据,然后在长时间运行的操作中阻塞线程,同时在其他线程上写入 Realm,则版本永远不会更新,并且 Realm 必须保留您的数据的中间版本可能实际上不需要,导致文件大小随着每次写入而增长。额外的空间最终将被未来的写入重用,或者可能被压缩——例如通过调用writeCopyToPath:error:.

为了避免这个问题,你可以打电话invalidate 告诉 Realm,你不再需要到目前为止从 Realm 读取的任何对象,这使我们无需跟踪这些对象的中间版本。Realm 将在下次访问时更新到最新版本。

在使用 Grand Central Dispatch 访问 Realm 时,您也可能会看到此问题。当 Realm 最终进入调度队列的自动释放池时,可能会发生这种情况,因为这些池在执行代码后的一段时间内可能不会被耗尽。RLMRealm在对象被释放之前,Realm 文件中数据的中间版本不能被重用 。为避免此问题,您应该在从调度队列访问 Realm 时使用显式自动释放池。

如果这些建议没有帮助,Realm 工程团队将很乐意对您的项目进行分析,以确定最小化文件大小增长的方法。您可以将代码私下发送至 help@realm.io。

于 2015-07-24T18:44:46.313 回答