首页 > 解决方案 > 当许多键的值相同时减少数据内存 C#

问题描述

我有很多以下文本形式的数据:

    4c5c,6c4h,486,30
    4c5c,6c5h,486,30
    4c5c,6c6h,458,0
    4c5c,6c7h,648,9
    4c5c,6c8h,648,9
    3sTs,QsKs,182,0
    3sTs,QsAs,182,0
    3sTs,KsAs,743,0
    3sJs,4s5s,495,0
    3sJs,4s6s,625,0
    3sJs,4s7s,739,0
    3sJs,4s8s,739,0
    3sJs,4s9s,739,0
    3sJs,4sTs,739,0
    3sJs,4sQs,182,0
    3sJs,4sKs,739,0
    3sJs,4sAs,625,0
    3sJs,5s6s,625,0
    3sJs,5s7s,739,0
    3sJs,5s8s,739,0

在每一行中,前 2 个术语代表一个键,后 2 个术语代表值。例如 KEY: 3sJs,5s8s VALUE: 739,0

我有超过 140 亿条这样的行,并且一直将它们存储在字典中以便快速访问。这是有问题的,因为大约 250GB 的文本数据在存储在字典中时需要大量内存。但是,我注意到多个键的许多值是相同的。是否有一些替代字典的方法,我可以通过减少内存需求来存储这些数据,以利用重复许多值的事实?我以前没有使用过带有 C# 程序的数据库,但做了一点 postgres - sqlite 是我最好/唯一明智的选择,它会将我的应用程序大小减少到可管理的分发大小吗?

标签: c#bigdata

解决方案


我不确定你的价值是多少。你能把你的价值观编码到多小?我将假设您可以将它们打包成 4 个字节。

因此,您的密钥是描述 4 张扑克牌的文本字符串。因此,您可能的密钥空间最多为52^4 ~= 7.3e6. 在所有可能的键中,哪个部分有值?离他们都近吗?

我不会使用文本字符串来表示您的密钥,而是为每张卡分配一个数字(0-51)。然后建立一个Int32密钥=k1 + k2*52 + k3*(52^2) + k4*(52^3)

如果要为大多数键存储值,则不需要字典。您可以只使用一个长度数组52^4。这样,您永远不需要为键本身分配任何内存。只需要4bytes * 52^4 ~= 28MBram。

然后将此数组存储在磁盘上,我会将其保存在 zip 存档中。如果您有许多相似的值,它应该可以很好地压缩。

您可能希望将此数据划分为多个部分,因此您不必将整个结构解压缩到内存中。但这取决于您希望在运行时如何使用这些数据。


推荐阅读