鉴于您的字符串数量非常多,您的选择必须关注以下几点:
1. Are your indexing structures going to fit in memory?
对于哈希表,答案显然不是。因此访问时间将比 O(1) 慢得多。您仍然只需要一次磁盘访问(整个插入过程将是 O(N))。
对于b-tree,我做了一些理论计算,假设b+tree(以节省内部节点的更多空间)并且内部节点被完全占用。通过这种分析,它不适合内存:
- 通常的磁盘页面大小为 4096 字节。那是一个 b-tree 节点的大小。
- 字符串的平均大小为 70 字节(越少越好)。
- 子节点地址有 4 个字节。
- 一个内部节点拥有 d 个键并有 d+1 个子地址:
**4096B = 4*(d+1)+70*d <=> d = 4096/75 => d = 54 **
* #internal nodes in memory -> #leaves nodes in disk -> #strings mapped*
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+tree)。这对于范围查询也很有用(我认为情况并非如此)。如果您的访问是完全随机的,那么哈希表会更快,因为它总是只需要一次磁盘访问,而 btree 需要对存储在磁盘中的每个级别进行磁盘访问。
如果您要进行少量访问,则最好使用 hashtable,因为插入总是更快。
由于您知道字符串的总数,因此您可以将其指示给哈希表,并且您不会在桶规模操作中浪费时间(这意味着要重新散列所有元素)。
注意:我发现了一些关于你的ukkonens后缀树的信息。插入是线性的,访问也是顺序的。但是我只发现它与一些 GB 一起使用。以下是关于后缀树算法的一些参考资料:[ref1]、[ref2]和[ref3]。
希望这会有所帮助...