【lucene】pointDimensionCount` vs `pointIndexDimensionCount`:
`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 数组(一块连续字节)
→ 因此 “数据只驻叶子”,内部节点纯当“路由”用。