我有对(key,value),其中包括key = string,value = int。我尝试从大型文本语料库中构建索引,因此我存储了字符串和标识符。对于我从语料库中读取的每个术语,我必须检查索引以查看它是否存在,因此我需要快速查找(如果可能,则为O(1))。我正在使用python字典来创建索引。问题是我走出Ram(16GB Ram)。我的替代方法是使用字典,当我的ram使用率为90%时,我使用sqlite3数据库将对存储到磁盘。但现在问题是寻道时间花了太多时间(首先检查dict,如果失败则去检查磁盘上的数据库)。
我正在考虑切换到Redis-db。我的问题是,我应该将键值作为字符串,还是应该哈希它们然后存储它们? (键是包含(2~100个字符)的字符串。那么值,我应该对它们做什么(值是int32数字)?
编辑:
我想存储每个术语及其标识符(唯一对),如果我读取一个术语并且它存在于索引中,则传递它。
EDIT2:
我尝试使用redis,但它看起来真的很慢(?),我使用相同的代码而不是字典我使用redis set&获得哪些应该具有O(1)复杂度,但索引的构建时间太慢。有什么建议吗?
答案 0 :(得分:0)
可以非常轻松地使用C哈希模拟Python字典。 Glib提供了一个工作的哈希实现,在一些C培训中不难使用。优点是Python字典会更快和(更多)内存耗尽:
https://developer.gnome.org/glib/2.40/glib-Hash-Tables.html
您还可以添加一些算法来提高性能。例如,存储压缩密钥。
更简单的是,您可以分段分割大型文本语料库,为每个部分创建独立索引,然后“合并”索引。
因此,例如索引1将显示:
key1 -> page 1, 3, 20
key2 -> page 2, 7
...
索引2:
key1 -> page 50, 70
key2 -> page 65
...
然后你可以合并索引1和2:
key1 -> page 1, 3, 20, 50, 70
key2 -> page 2, 7, 65
...
您甚至可以对N台机器进行并行化。
答案 1 :(得分:0)
我应该将键值存储为字符串还是应该哈希它们然后存储它们? [......]价值观怎么样?
在您的情况下,最简单的使用Redis的方法是为每个唯一对执行SET
,例如SET foo 1234
等。
正如Instagram(x)所证明的,你可以做的是使用Redis Hashes,它在幕后具有透明的内存优化功能:
哈希[...]何时 小于给定数量的元素,并且最大元素 大小,以高效内存编码方式编码,最多使用10个 少花点时间
(有关详细信息,请参阅Redis memory optimization文档。)
根据Instagram的建议,你可以做的是:
n = hash(key)
b = n/1000
(每个存储区包含1,000个元素)i
)对存储在此存储桶中:HSET b n i
注意:保持整数值i
不变,因为在幕后整数使用ziplists中的可变字节数进行编码。
当然请务必使用hash-max-ziplist-entries 1000
配置Redis,以确保每个哈希值都经过内存优化(xx)。
要加快初始插入速度,您可能希望通过mass insertion使用原始Redis协议。
(x)Storing hundreds of millions of simple key-value pairs in Redis。
修改强>:
(xx)即使在实践中,由于哈希函数的稀疏性,哈希的大多数(如果不是全部)哈希将包含单个元素。换句话说,由于你的密钥是经过散列的字符串而不是像Instagram中那样单调增加ID,因此这种方法可能 NOT 在内存节省方面同样有趣(所有的ziplists都包含一对)。与基本SET key(= string) value(= integer)
方法相比,您可能希望加载数据集并查看其对实际数据的作用。