高效(时间和空间)字典数据库(唯一字到唯一ID和后面)

时间:2011-01-19 22:57:04

标签: python c database encoding dictionary

我正在寻找能够解决的解决方案:

  • 存储任意大小的唯一字,以及它们唯一的64位无符号整数标识符和32或64位无符号int引用计数
  • 使用以下模式快速访问数据:
    • 查找单词,返回其uint64标识符
    • 查找标识符,返回单词
  • 插入新记录,最好使用自动递增标识符和原子递增的引用计数,最好是批量提交(不是逐字逐句,每个都在单独的事务中,但在一个已提交的事务中有几个字)
  • 以原子方式删除记录,其引用次数为零(即使使用速率受限的全表扫描,也可以通过遍历所有记录并删除事务中0引用的记录来完成)
  • 在传统的纺纱生锈(硬盘)上存储大量记录,记录数量在1亿到1000亿之间(1000 * 10 ^ 9)
  • 平均字大小介于25-80字节之间
  • 最好有一个python(用于原型设计)和C接口,主要是可嵌入的,或者是一个高效的“远程”(只能在localhost上)API

例如,MySQL模式将是这样的:

CREATE TABLE words (
    id SERIAL,
    word MEDIUMTEXT,
    refcnt INT UNSIGNED,
    INDEX(word(12)),
    PRIMARY KEY (id)
)

这当然有效,但MySQL无法完成这项任务,并且由于搜索所需的索引,它会不必要地存储冗余信息。

在搜索最有效的解决方案期间,我发现了以下内容:   - 因为这些词有很多共同点(大多数是各种语言和字符集中的普通字典词),所以:http://www.unixuser.org/~euske/doc/tcdb/index.html会很好   - 迄今为止我能找到的最好的东京内阁的TDB:packages.python.org/tokyocabinet-python/TDB.html,但我必须评估它的性能和可能的设置(在哪里存储什么,并使用什么样的索引在哪里以获得最佳时间和空间效率)

任何想法,算法,更好的,随时可用的产品和设置?

谢谢,

1 个答案:

答案 0 :(得分:2)

您可能想要try Redis。它涵盖了大多数(如果不是全部) 你的要求。它具有良好的性能,适用于您的用例,具有原子性 用于创建引用计数和唯一标识符的递增/递减, many languages including Python and C存在客户端,您可以进行换行 事务中的命令序列。它还支持列表,集合和排序 设置和其他一些您可能会觉得有用的功能。

如果您可以对工作进行分区,则可以从多个数据加载/处理数据 主机并行。鉴于redis的速度,您可能不需要批量处理 但这是可能的(MSET命令)。

另一个不错的方面是您可以使用命令行与Redis进行交互 redis-cli命令。这样你就可以试用/调试序列了 尝试编写任何代码之前的命令。假设redis正在运行 localhost,使用默认端口,键入:

% redis-cli
redis>

我写了一组支持你的用例的快速命令。

此代码段创建一个名为next.words.id的整数键,并将其递增 原子地,返回新值。为了便于说明,我在123455开始了序列。 (integer) 123456是值 退回给你的客户:

redis> SET next.words.id 123455
OK
redis> INCR next.words.id
(integer) 123456

然后我们将单词映射到其ID "chaos" -> 123456,然后创建一个反向 从id:123456 -> "chaos"映射,最后创建引用计数键 设为0。前缀id:ref:以及next.words.id只是 我选择的约定 - 你可以使用你喜欢的任何命名。

redis> SET chaos 123456
OK
redis> SET id:123456 chaos
OK
redis> SET ref:chaos 0
OK

增加单词“chaos”的引用计数:

redis> INCR ref:chaos
(integer) 1
redis> INCR ref:chaos
(integer) 2

要减少引用计数,请使用DECR:

redis> DECR ref:chaos
(integer) 1
redis> DECR ref:chaos
(integer) 0

此时您的代码可以检测到“ chaos ”的引用计数 0并在单个事务中执行以下命令:删除 单词及其id:ref:键。我使用WATCH命令来避免竞争条件:如果任何其他客户端在我们的事务提交之前更改了ref:chaos密钥,它将被中止。

redis> WATCH ref:chaos
OK
redis> GET chaos
(integer) 123456
redis> MULTI
redis> DEL chaos
QUEUED
redis> DEL id:123456
QUEUED
redis> DEL ref:chaos
QUEUED
redis> EXEC
1) (integer) 1
2) (integer) 1
3) (integer) 1

希望这有帮助。