您将如何最小化或压缩 Core Data sqlite 文件大小?

Posted

技术标签:

【中文标题】您将如何最小化或压缩 Core Data sqlite 文件大小?【英文标题】:How would you minimize or compress Core Data sqlite file size? 【发布时间】:2011-10-21 23:29:00 【问题描述】:

我有一个 215MB 的 csv 文件,我已对其进行解析并存储在核心数据中,该核心数据包含在我自己的自定义对象中。问题是我的核心数据 sqlite 文件大约 260MB。 csv 文件包含关于我所在城市的交通系统(公交车站、时间、路线等)的大约 450 万行数据。

我尝试修改属性,以便将表示停止时间的字符串数组存储为 NSData 文件,但由于某种原因,文件大小仍保持在 260MB 左右。

我无法发布这么大的应用程序。我怀疑有人会想要下载一个 260MB 的应用程序,即使这意味着他们有整个城市的交通时间表。

有什么方法可以压缩或最小化使用的存储空间(即使不使用核心数据,我也愿意听取建议)?

编辑:我现在只想提供更新,因为我一直难以置信地盯着文件大小。通过一些涉及字符串、索引和数据库规范化的巧妙操作,我设法将压缩后的大小减小到 6.5MB 或 2.6MB。 Core Data 中存储了大约 105,000 个对象,其中包含该城市交通系统的全部详细信息。我现在几乎要流泪了 D':

【问题讨论】:

我刚刚看到您对最终尺寸的更新评论。非常令人印象深刻。真实世界数据的 100:1 压缩应该让任何人感到自豪。 很晚,但如果您查看应用程序 Transit,我已经与他们交谈过,他们已设法将 260MB 减少到仅 800KB 【参考方案1】:

除非您的原始 CSV 以非常愚蠢的方式编码,否则无论您压缩多少,大小似乎都不会低于 100M。对于应用程序来说,这仍然很大。解决方案是将数据移动到 Web 服务。您可能想要下载和缓存重要部分,但如果您正在谈论数百万条记录,那么从服务器获取似乎是最好的。此外,我不得不相信,公交系统时不时会发生变化,每次调整一个站点都必须升级一个几十MB的应用程序,这将是令人沮丧的。


我已经说过了,但实际上你可以考虑一些事情:

将布尔值移动到位字段中。您可以将 64 个布尔值放入 NSUInteger。 (如果您只需要 8 位,请不要使用完整的 64 位整数。尽可能存储最小的内容。) 压缩存储时间的方式。一天只有1440分钟。您可以将其存储在 2 个字节中。中转时间一般不会到秒;他们不需要 CGFloat。 星期几和日期也可以类似地压缩。 显然你应该规范化任何字符串。查看 CSV 文件中的多行重复字符串值。 对于此类问题,我通常会推荐使用原始 sqlite 而不是核心数据。 Core Data 更多的是关于对象持久性而不是原始数据存储。您看到 CSV 有 20% 的膨胀(其本身效率不高)这一事实并不是解决这个问题的好方向。 如果您想变得更紧密,并且不需要非常好的搜索功能,您可以创建打包数据 blob。我曾经在内存非常紧张的电话交换机上执行此操作。您创建一个位域结构并为一个变量分配 5 位,为另一个变量分配 7 位,依此类推。这样,再经过一段时间的洗牌,使它们在字边界上正确排列,您会变得非常紧凑。

由于您最关心您的初始下载大小,并且可能愿意稍后扩展您的数据以获得更快的访问速度,因此您可以考虑非常特定于域的压缩。例如,在上面的讨论中,我提到了如何一次减少到 2 个字节。在许多情况下,通过将时间存储为自上次以来的增量分钟,您可能会减少到 1 个字节(因为如果它们是公共汽车和火车时刻表,您的大部分时间总是会以相当小的步骤增加)。放弃数据库,您可以创建一个编码非常紧密的数据文件,您可以在首次启动时将其提取到数据库中。

您还可以使用特定领域的知识将您的字符串编码为更小的标记。如果我对纽约地铁系统进行编码,我会注意到一些字符串出现了很多,例如“Avenue”、“Road”、“Street”、“East”等。我可能会将它们编码为不可打印的 ASCII,例如 ^ A、^R、^S、^E 等。我可能会将“138 Street”编码为两个字节 (0x8A13)。这当然是基于我的知识,即 è (0x8a) 从未出现在纽约地铁站。这不是一个通用的解决方案(在巴黎可能是个问题),但它可以用来高度压缩您有特殊知识的数据。在华盛顿这样的城市,我相信他们编号最高的街道是第 38 街,然后是 4 值方向。因此,您可以将其编码为两个字节,首先是“编号街道”令牌,然后是一个位字段,其中 2 位用于象限,6 位用于街道编号。这种想法可能会显着缩小您的数据大小。

【讨论】:

我完全同意你的看法。但是,该应用程序旨在能够离线运行,这意味着必须包含所有数据。否则这实际上已经超出了我的想法,并且会很理想。 是的;我在思考如何更好地存储 CSV。我认为有很多选择。 CSV 真的没有那么高效。我认为你可以从 gzip 中得到的任何东西都可以从更聪明的存储解决方案中得到更好的结果。 感谢 Rob 的周到回复。我浏览了数据库,发现很多信息都在重复,尤其是头标,每个都存储为字符串。现在检查代码以消除它。我喜欢你关于增量时间的建议,我会试一试。希望我可以将这个野兽压缩到 200MB 以下,然后在第一次运行时将其压缩并解压缩到缓存文件夹中。 我知道你对此有一个或两个想法!【参考方案2】:

您也许能够执行一些数据库规范化。

查找可能是多余的或存储在多行中的相同值的任何内容。您可能需要重组数据库,以便将这些重复值(如果有)存储在单独的表中,然后通过 id 从它们的原始行中引用。

【讨论】:

【参考方案3】:

sqlite 文件压缩到多大?如果它足够小,最简单的方法是将其压缩,然后将其解压缩到 NSCachesDirectory。

【讨论】:

“压缩”是指用 gzip 压缩,顺便说一句。 压缩后文件大小为 57.7MB。你可能会在这里做一些事情。我现在唯一担心的是手机解压缩它通常需要多长时间。

以上是关于您将如何最小化或压缩 Core Data sqlite 文件大小?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查关系是不是已建立 - Core Data

Core Data/SQLite 是不是压缩冗余信息?

sql注入靶场搭建

在 Core Data iPhone 应用程序的视图层次结构中保存位置

如何调整 Core Data 默认缓存的行为或大小?

如何正确使用 Core Data 验证和错误框架?