数百万对Redis / Dictionaries / sqlite3

时间:2014-07-19 19:47:54

标签: python database dictionary redis

我有对(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)复杂度,但索引的构建时间太慢。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

可以非常轻松地使用C哈希模拟Python字典。 Glib提供了一个工作的哈希实现,在一些C培训中不难使用。优点是Python字典会更快和(更多)内存耗尽:

https://developer.gnome.org/glib/2.40/glib-Hash-Tables.html

GLib Hash Table Loop Problem

您还可以添加一些算法来提高性能。例如,存储压缩密钥。

更简单的是,您可以分段分割大型文本语料库,为每个部分创建独立索引,然后“合并”索引。

因此,例如索引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的建议,你可以做的是:

  1. 使用64位散列函数散列每个键:n = hash(key)
  2. 计算相应的存储分区:b = n/1000(每个存储区包含1,000个元素)
  3. 将哈希值(= i)对存储在此存储桶中:HSET b n i
  4. 注意:保持整数值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)方法相比,您可能希望加载数据集并查看其对实际数据的作用。