详细解释 hash.k2d taxo.k2d opts.k2d

最后发布时间 : 2026-02-14 14:26:13 浏览量 :

很好,这个问题已经进入 Kraken2 内核级理解了。
我们把 hash.k2dtaxo.k2dopts.k2d 拆开讲,从:

  1. 文件本质
  2. 内部数据结构
  3. 内存加载方式
  4. 运行时如何配合
  5. 和算法的对应关系

逐层解释。


一、整体结构关系

Kraken2 数据库构建完成后核心文件:

hash.k2d   → k-mer → taxid 映射表(核心)
taxo.k2d   → taxonomy 树结构
opts.k2d   → 构建参数

运行时:

读取 opts.k2d
读取 taxo.k2d
mmap hash.k2d
开始 classify

二、hash.k2d(最核心文件)

1️⃣ 本质是什么?

一个 压缩版 k-mer → taxid 的最小完美哈希表

但不是普通哈希表,而是:

Compact Hash Table + Minimizer 索引


2️⃣ Kraken2 的核心算法

Kraken2 不存所有 k-mer,而是:

  • 每个 k-mer 提取 minimizer
  • 用 minimizer 做索引
  • 存 minimizer → LCA taxid

所以:

k-mer  → minimizer → hash lookup → taxid

3️⃣ 内部结构

简化理解为:

[ header ]
[ hash table buckets ]
[ value array ]

header 内容包括:

  • k-mer 长度
  • minimizer 长度
  • 哈希表大小
  • load factor
  • version

4️⃣ 存储结构(逻辑模型)

概念化结构:

struct Bucket {
    uint64_t minimizer_key;
    uint32_t taxid;
}

但真实实现更复杂:

  • 使用 bit-packed 结构
  • 2bit 编码 DNA
  • open addressing
  • linear probing

5️⃣ 为什么文件这么大?

如果数据库大:

  • 数十亿 minimizer
  • 每个 entry 至少 8~12 bytes

标准数据库可达 30~60GB。


6️⃣ 运行时如何加载?

如果不加 -M:

读取整个 hash.k2d 到内存

如果加 -M:

mmap() 映射
按需加载页

所以 -M 适合内存不足机器。


三、taxo.k2d(taxonomy 文件)

这个文件是:

NCBI taxonomy 的压缩内存结构版本


1️⃣ 作用

当多个 k-mer 命中不同 taxid 时:

计算 LCA(lowest common ancestor)

需要一棵 taxonomy 树。


2️⃣ 内部结构

逻辑模型:

struct TaxNode {
    uint32_t taxid;
    uint32_t parent;
    uint32_t rank;
}

实际上是:

  • 一个连续数组
  • index = taxid
  • O(1) 找 parent

3️⃣ 为什么不是直接用 names.dmp / nodes.dmp?

因为:

  • 原始文件太慢
  • 需要 runtime 快速查 LCA
  • 需要连续内存结构

所以构建时:

nodes.dmp → internal compact tree → taxo.k2d

4️⃣ LCA 计算方式

Kraken2 使用:

while taxid_a != taxid_b:
    上升到 parent

优化版本使用:

  • depth cache
  • precomputed path compression

四、opts.k2d(构建参数)

这是最简单的文件。


1️⃣ 内容是什么?

构建数据库时使用的参数:

  • k-mer 长度
  • minimizer 长度
  • spaced seed pattern
  • hash table size
  • version

2️⃣ 为什么必须要?

防止运行时参数不匹配:

比如:

数据库 k=35
运行时却用 k=31

那结果完全错误。

所以 classify 启动时:

读取 opts.k2d
验证参数一致

五、三者如何协作?

运行 classify 时逻辑:

1. 读取 opts.k2d
2. 加载 taxonomy(taxo.k2d)
3. mmap hash.k2d
4. 读取序列
5. 切 k-mer
6. 提取 minimizer
7. hash lookup
8. 得到 taxid
9. 多个 taxid → LCA
10. 输出结果

六、文件大小对比(典型)

文件大小作用
hash.k2d95%k-mer 索引
taxo.k2d很小taxonomy 树
opts.k2d几 KB参数

七、为什么叫 .k2d?

k2d = Kraken2 Database


八、和 Kraken1 的区别

Kraken1:

  • 存所有 k-mer
  • 巨大内存占用(~100GB)

Kraken2:

  • minimizer 技术
  • 减少 85% 内存
  • 使用 compact hash

九、深入到算法层

Kraken2 本质是:

空间优化的 k-mer 精确匹配分类器

核心技术:

  • minimizer
  • compact hash table
  • LCA 分类
  • 2bit DNA 编码

十、如果你想再深入

我可以继续讲:

1️⃣ hash.k2d 的真实二进制布局
2️⃣ Kraken2 的 CompactHashTable C++ 实现
3️⃣ minimizer 为什么能减少内存
4️⃣ LCA 统计策略为什么准确
5️⃣ 如何自己写一个 mini-kraken

你想深入哪个层面?