鉴于你有大量字符串,你的选择必须关注几个要点:
1. Are your indexing structures going to fit in memory?
对于
哈希表来说,答案显然是否定的。因此,访问时间将比O(1)慢得多。不过,你只需要一个磁盘访问(整个插入过程的复杂度将是O(N))。
对于
b-tree,我进行了一些理论计算,假设使用
b+tree(为了在内部节点中节省更多的空间),并且内部节点被完全填满。通过这个分析,它无法放入内存:
- 通常的磁盘页面大小为4096字节。那是一个b树节点的大小。
- 您的字符串的平均大小为70字节(如果它更小,就越好)。
- 子节点地址有4个字节。
- 内部节点包含d个键,并且有d+1个子节点地址:
** 4096B = 4 * (d + 1) + 70 * d <=> d = 4096/75 => d = 54 **
* #在内存中的内部节点 -> 在磁盘中的叶子节点 -> 映射的字符串数量*
0个内部节点 -> 1个叶子节点 -> 映射了53个字符串
1个内部节点 -> 使用了54个叶子节点(每个叶子节点有53个叶子) -> 映射了53²个字符串
1+54个内部节点 -> 使用了54²个叶子节点 -> 映射了53³个字符串
...
...+54⁵个内部节点 -> 使用了54⁶个叶子节点 = 映射了53⁷个字符串
53⁷ > 10^12 , but 54⁵*4096 bytes > 1TB of memory
如果您的字符串不是均匀分布的,则可以探索常见前缀。这样,内部节点可能能够寻址更多的子节点,从而节省内存。
BerkeleyDB具有该选项。
2. What kind of access are you going to employ? Large or small number of reads?
If you have large number of reads, are they random or sequential?
如果您的访问是顺序的,那么即使您使用 btree,您仍然可能会受益,因为您将经常使用缓存节点(不需要磁盘访问),并且叶子节点是按顺序链接的(b+树)。这对于范围查询也非常有用(我认为这不是情况)。如果您的访问完全随机,则 hashtable 更快,因为它始终只需要一个磁盘访问,而 btree 需要每个存储在磁盘中的级别都需要一个磁盘访问。
如果您要进行少量访问,则由于插入速度始终更快,建议使用 hashtable。
由于您知道字符串的总数,因此可以将其指示给 hashtable,并且您将不会浪费时间进行桶规模操作(这意味着所有元素都需要重新哈希)。
注意:我找到了关于你的
ukkonens后缀树的一些信息。插入是线性的,访问也是顺序的。然而,我只发现它被用于一些GB级别的数据。这里有一些关于后缀树算法的参考资料:
[ref1],
[ref2] 和
[ref3]。
希望这能在某种程度上有所帮助...