1

我有一个非常定期查询数据库的应用程序。它返回多达数百万个字符串,其中绝大多数是 bieng 重复。我需要将所有这些记录存储在内存中,并试图最小化占用空间。

我目前的设计是在每个字符串上调用 GetHashCode(),然后存储哈希而不是字符串本身。

然后我尝试将其添加到Dictionary<hashcode,string>()结构中。我还保留了第二个字典,Dictionary<hashcode,count>()随着更多条目使用该字符串,该字典将递增\递减。

在条目处理方法中,我递减计数器,如果使用量降至零,则从字典中删除字符串。

所以,有几个问题:

这是愚蠢的差事吗?是否有一些我可以使用的数据类型可以比与这个巨头合作节省大量时间\精力?

我希望我的字符串表是线程安全的(目前不是)。使用 ConcurrentDictinary 是我最好的选择吗?

提前致谢。

4

3 回答 3

1

这样做的主要问题是两个不同的字符串可以具有相同的哈希码。

听起来你让这变得比它需要的更复杂。你需要的是实习:

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

CLR 已经维护了一个字符串实例表以节省内存。

更新

但是...您应该牢记文档中的警告:在 CLR 卸载之前,不会对实习字符串进行垃圾收集,即它们在您的应用程序域的生命周期内一直存在。

但是您可以很容易地自己实现相同的模式:

class LocalStringInterner
{
    private Dictionary<string, string> _strings = new Dictionary<string, string>();

    public string Intern(string str)
    {
        string interned;
        if (_strings.TryGetValue(str, out interned))
            return interned;

        _strings.Add(str, str);
        return str;
    }
}

这样,当您不再需要那组字符串时,您可以放弃LocalStringInterner.

为了使其在多个线程中使用安全,您可以将主体包装Intern在一个lock(_strings).

于 2012-12-05T13:54:07.163 回答
0

也许 md5-Hash 可以帮助你。它应该(理论上)是唯一的,并且受到大多数数据库的支持(如果不是 C# 将帮助您)。

MySQL:

SELECT name, md5(name)
FROM user

也就是说,我会考虑一种更好的数据库方法。

如果您在服务器端的每个字符串都有一个唯一的 id,这应该是一件容易的事。

假设您有一个名为string_resourcesauto_incrementid列和varchar字段的表。我还将添加一个唯一索引value以确保您不会两次存储字符串。

|id     | value          |
|1      | Hello          |
|2      | World          |
...
|145789 | Something else |

现在您可以将 int 值存储在字典中

md5: 128bit
int32: 32bit  // <-- You Don't Say?
于 2012-12-05T14:06:23.317 回答
0

我没有看到获取哈希码并将字符串存储在 aDictionary<hash,string>中以及将计数存储在单独的字典中的意义。您可以使用字符串本身作为键,字典将自动(内部)创建和存储哈希码。因此,仅使用一本字典Dictionary<string,count>就足够了。您还可以通过 . 从字典中检索字符串dict.Keys

两个不同字符串的哈希码可以相同。这称为碰撞。自动处理这些Dictionary<TKey,TValue>碰撞。

ConcurrentDictinary<TKey,TValue>似乎是合适的;但是,我对此没有任何经验。

于 2012-12-05T14:37:41.613 回答