【lucene】pointDimensionCount` vs `pointIndexDimensionCount`:

发布于:2025-09-13 ⋅ 阅读:(21) ⋅ 点赞:(0)

`pointDimensionCount` vs `pointIndexDimensionCount`:

 

一个管“数据维度”,一个管“索引维度”——

 

后者只在对多维点做“数据降维”(`MultiDimensionCounter`)时才比前者小,其余场景俩值相等。

 

---

 

1. 数据维度 `pointDimensionCount`

 

- 你实际 add 的维度个数  

  

```java

  new IntPoint("pos", x, y, z) // 3 维 → pointDimensionCount = 3

  ```

 

- 决定 每个点值 packed 后的总字节

 

  `packedBytesLength = pointDimensionCount * bytesPerDim`

- 查询时 visitor 比较的维度数也是它

 

---

 

2. 索引维度 `pointIndexDimensionCount`

 

- 真正用来建 BKD 树的维度数

 

  默认 等于 `pointDimensionCount`  

- 唯一例外:`LongPoint.newDistanceQuery` / `LatLonPoint`

 

  它们内部用 MultiDimensionCounter 把 2D 经纬度映射到 1D 希尔伯特曲线

 

  → 于是  

  

```

  pointDimensionCount = 2 (原始数据)

  pointIndexDimensionCount = 1 (实际只建 1 维 BKD)

  ```

 

- 值更小 → BKD 树节点分裂只在这 1 维上进行,packed 索引字节减半,比较次数减半,剪枝更快

 

---

 

3. 代码里怎么用

 

场景 值 

普通 `IntPoint` 3D `3 == 3` 

`LatLonPoint` 2D `2 > 1` 

用户自建 `MultiDimensionCounter` 用户定 

 

写入时:

- 数据维度决定 `.dim` 叶子块里每个点值的字节数

- 索引维度决定 BKD 内部节点分裂维度数 与 packed 索引字节数

 

查询时:

- visitor 比较只按 索引维度来,数据维度多余的维被忽略

---

✅ 一句话总结

> `pointDimensionCount` = 你原始 add 的维数

`pointIndexDimensionCount` = 实际拿去建 BKD 的维数

后者只在降维索引(如经纬度→希尔伯特)时比前者小,用来加速剪枝、减少索引体积。

 

BKD 树里只存 1 维——

把 2D 经纬度通过 希尔伯特曲线 映射成 1 条 64 bit 长整型后,

整个 BKD 按这 1 维分裂、排序、打包,物理上就是 1D 数据;

原来的 2D 坐标只出现在 叶子块的“数据区”(用于最终精确过滤),不参与树结构。

---

数据流一眼看清

阶段 维度 内容 

用户 add 2D `lat 39.9°, lon 116.4°` 

写入时 1D `long hilbert = hilbert(lat, lon)` → 64 bit 值 

BKD 节点分裂 1D 只比较这 1 个 long 

叶子块 2D+1D packed 2D 坐标(用于最终过滤) + docID 

 

---

小结

> BKD 骨架 = 1 维 long

叶子附带 2D 原始坐标(供查询时二次精确过滤)

既享受 1D 树的高剪枝效率,又不丢失 2D 精度。

 

BKD 树 = 二叉、二维划分、深度优先存储  

- 内部节点只存 分裂维度 + 分裂值 + 左右子偏移(无 docID,无点值)  

- 叶子节点才存 真正的 packed 点值数组 + docID 数组(一块连续字节)  

 

→ 因此 “数据只驻叶子”,内部节点纯当“路由”用。


网站公告

今日签到

点亮在社区的每一天
去签到