我正在使用Realm作为我的应用程序的数据库解决方案。我的图像需要持久存储能力,所以我可以在离线时加载它们。我还需要一个缓存,所以我可以从那里加载图像,而不是每次单元格绘制时从API中获取它们。我的第一个想法是,如果我要将Realm中的图像存储为NSData,那么Realm数据库可以很好地服务这两个函数。但是我在SE(here和here)上找到了两个答案,如果您有许多经常变化的大尺寸图像,建议不要这样做。相反,他们建议将图像保存到磁盘,然后将URL存储到Realm中的那些图像。
我的问题是为什么这是最佳做法?与上述相关的答案没有给出理由,除非说你最终得到了一个膨胀的数据库。但为什么这是一个问题呢?在我的数据库中拥有大量图像与在磁盘上拥有大量图像之间有什么区别?
是速度问题吗?如果是这样,应用程序是否能够从磁盘访问映像以及能够从Realm等数据库解决方案访问映像时是否存在明显的速度差异?
提前致谢。
答案 0 :(得分:11)
这实际上只是一个本地化到Realm的问题。我记得Core Data也给出了同样的建议。
我猜测最重要的原因是为什么不建议将大二进制数据存储在数据库中是因为“你没有获得任何东西,实际上是站在一起比你原本会失去的更多。
使用Core Data(即由SQLite支持的数据库),当您从SQLite执行读取时,数据将被复制到内存中,实际上会受到性能影响。如果它是大量数据,那么这是完全不可接受的。
至少使用Realm,因为它使用零拷贝,内存映射机制,你将直接从Realm文件提供NSData
映射,但是再次,这绝对不是不同于你只是从磁盘本身加载图像文件。
当这成为Realm中的主要问题时,您经常会开始更改图像。在处理跨线程更改数据时,Realm实际上使用内部快照机制,但这实际上意味着在操作期间,整个数据集可能会定期在磁盘上复制(以确保线程安全)。如果数据集包含大量二进制数据,那么这些数据集也会重复(这也可能意味着性能受到影响)。发生这种情况时,将增加磁盘上Realm文件的大小以容纳快照,但是当操作完成并删除快照时,文件将不会缩回到其原始大小。这是因为回收磁盘空间将是一个代价高昂的性能损失,并且由于很容易再次需要空间(即通过另一个大型快照操作),因此先发制人的做法似乎效率低下(因此& #39;膨胀&#39)。
如果需要,可以手动执行操作以回收此磁盘空间,但通常建议的方法是优化代码,以最大限度地减少这种情况。
因此,总而言之,尽管你可以将大数据blob保存到数据库,但随着时间的推移,它可能会导致性能命中和文件大小膨胀,否则你可能会避免这种情况。这些类型的数据库旨在帮助将少量数据转换为可以保存到磁盘并从磁盘中检索的格式,因此它基本上浪费在二进制文件上,无需任何修改即可轻松直接保存。
将大型二进制数据简单地存储在磁盘上通常更容易,更清晰,更高效,只需在数据库中存储文件名引用即可。 :)