- 向量数据库
- 数据库
- 人工智能
- 后端
【免费下载链接】lancedb
Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.
导读
IndexStatistics是 LanceDB Node.js SDK(@lancedb/lancedb)中描述单个索引运行状态的核心数据结构。当你对表中的向量列、标量列或全文检索列创建索引后,可以通过Table.indexStats(name)获取该索引的统计信息,用于判断索引覆盖率、索引类型、距离度量以及分片数量。本文以官方接口文档为骨架,结合仓库中的 Rust 原生实现、TypeScript 绑定与测试用例,逐字段解读IndexStatistics的语义与取值,并给出完整的实战调用示例,帮助你掌握"建索引—查统计—评估覆盖率—决定是否重训/优化"的完整工作流。
接口概览:IndexStatistics 定义了什么
IndexStatistics接口定义于 docs/src/js/interfaces/IndexStatistics.md,它由 5 个字段组成:
| 字段 | 类型 | 是否可选 | 含义 |
|---|---|---|---|
indexType | string | 必选 | 索引的类型 |
numIndexedRows | number | 必选 | 被该索引覆盖的行数 |
numUnindexedRows | number | 必选 | 未被索引覆盖的行数 |
distanceType | string | 可选 | 索引使用的距离函数类型,仅向量索引存在 |
numIndices | number | 可选 | 该索引被拆分成的分片(part)数量 |
该接口并非凭空定义,而是由 Node 原生模块中的同名结构体直接映射而来。在 nodejs/src/table.rs 中,#[napi(object)]修饰的IndexStatistics结构体完整对应上述五个字段,并通过From<lancedb::index::IndexStatistics>将 Rust 核心库的统计结果转换为 JS 可读的对象。因此,文档中字段的类型语义(如num_indexed_rows为f64、num_indices为Option<u32>)与底层保持一致,undefined即对应 Rust 侧的None。
获取索引统计:Table.indexStats(name)
IndexStatistics的典型获取方式是调用Table.indexStats(name):
abstract indexStats(name: string): Promise<IndexStatistics | undefined>;接口定义见 nodejs/lancedb/table.ts。需要特别注意两点:
- 返回值为
undefined的情形:当指定名称的索引不存在时,该方法返回undefined而非抛错。实现在 nodejs/lancedb/table.ts 中,底层inner.indexStats(name)返回null时被转换为undefined。 - 索引名称来源:索引名通常由 SDK 自动生成(如对
vec列建索引会生成vec_idx),建议先通过Table.listIndices()获取索引名称列表,再逐个查询统计。
底层调用链为:Table.indexStats→ 原生table.index_stats(index_name)(nodejs/src/table.rs)→ Rust 核心库lancedb::Table::index_stats(rust/lancedb/src/table.rs)。Rust 侧的注释明确说明:索引不存在时返回None,这一语义贯穿到各语言 SDK。
完整示例:创建索引并读取统计
import * as lancedb from "@lancedb/lancedb"; const db = await lancedb.connect("data/sample-lancedb"); const table = await db.createTable("my_table", [ { id: 1, vector: [0.1, 1.0], item: "foo", price: 10.0 }, { id: 2, vector: [0.2, 0.9], item: "bar", price: 20.0 }, ]); // 1. 创建标量索引 await table.createIndex("id"); // 2. 查询统计 const stats = await table.indexStats("id_idx"); if (stats) { console.log(stats.indexType); // 例如 "BTREE" console.log(stats.numIndexedRows); // 已建索引的行数 console.log(stats.numUnindexedRows);// 尚未入索引的行数 console.log(stats.distanceType); // undefined(标量索引无距离函数) console.log(stats.numIndices); // 分片数 } // 3. 查询不存在的索引会得到 undefined const missing = await table.indexStats("some non-existent index"); console.log(missing); // undefined字段逐项解读
indexType:索引类型
必选字段indexType: string表示索引的类型。从 Python 侧的类型定义(python/python/lancedb/table.py)可以看到,LanceDB 支持的索引类型包括向量索引(IVF_FLAT、IVF_SQ、IVF_PQ、IVF_RQ、IVF_HNSW_SQ、IVF_HNSW_PQ、IVF_HNSW_FLAT)以及标量/全文索引(FTS、BTREE、BITMAP、LABEL_LIST)。Node SDK 中indexType为字符串,值由底层IndexType::to_string()生成(nodejs/src/table.rs)。
在 rust/lancedb/src/index.rs 的单元测试中可以看到索引类型名称的规范化逻辑:例如NGram的规范输出为NGRAM,BloomFilter为BLOOM_FILTER,RTree为RTREE,同时兼容大小写与下划线变体解析。这意味着你在比较indexType字符串时,应以规范大写形式为准。
numIndexedRows 与 numUnindexedRows:索引覆盖率
这一对字段是评估索引健康度的核心:
numIndexedRows: number:被该索引覆盖的行数;numUnindexedRows: number:未被该索引覆盖的行数。
Rust 核心层的定义(rust/lancedb/src/index.rs)明确指出num_unindexed_rows是"尚未被加入索引的行"(These are rows that haven't yet been added to the index)。因此,当表持续add新数据而索引未更新时,numUnindexedRows会增长;此时查询可能退化为全表扫描或部分回退,需要通过optimize()(触发索引增量更新)来提升覆盖率。
测试 python/python/tests/test_table.py 完整演示了这一生命周期:先建索引时num_indexed_rows == 2,随后add一行数据,此时再查询统计会发现已索引行数仍为 2;执行optimize()后num_indexed_rows更新为 3,未索引行数归零。
distanceType:距离函数(仅向量索引)
可选字段distanceType?: string只在向量索引上存在;标量索引与全文检索(FTS)索引没有距离函数,因此该字段为undefined。文档注释(docs/src/js/interfaces/IndexStatistics.md)与 Rust 源码注释(nodejs/src/table.rs)保持一致。
从 Python 测试(python/python/tests/test_index.py)可以归纳出常见取值:
| 索引/场景 | distanceType 取值 |
|---|---|
| IVF_PQ / IVF_SQ / IVF_FLAT(浮点向量) | "l2" |
| 二进制向量(IVF_FLAT) | "hamming" |
| BITMAP / BTREE 等标量索引 | undefined/None |
该字段本质上来自 Rust 侧的Option<DistanceType>,仅在向量索引元数据中记录metric_type(见 rust/lancedb/src/index.rs)。
numIndices:分片数量
可选字段numIndices?: number表示该索引被拆分成多少个部分(parts)。向量索引在创建时可指定numPartitions等训练参数,最终索引会被拆分为多个分片;该字段即反映这一拆分结果。在测试 nodejs/test/table.test.ts 中,默认创建索引后numIndices为1。
结合源码的进阶认识
统计数据的底层来源
Rust 核心库中IndexStatistics的构建来自IndexStatisticsImpl(rust/lancedb/src/index.rs),它反序列化底层 Dataset 返回的index_statistics()JSON,包含num_indexed_rows、num_unindexed_rows、indices(其中含metric_type)和num_indices。也就是说,你在 JS 中读到的统计字段最终来源于存储引擎(Lance format)层面的索引元数据,而非实时扫描计算。
跨语言一致性
同一个概念在三种 SDK 中保持一致的语义与命名:
- Node.js:
IndexStatistics接口(本文主题),字段为 camelCase; - Python:
IndexStatisticsdataclass(python/python/lancedb/table.py),字段为 snake_case(num_indexed_rows、distance_type等),并保留了对旧字典式访问的兼容(__getitem__); - Rust:
lancedb::index::IndexStatistics(rust/lancedb/src/index.rs)。
Python 测试 python/python/tests/test_remote_db.py 还展示了远程云表的统计响应格式(index_type、num_indexed_rows、num_unindexed_rows),说明该数据结构在本地嵌入模式与云服务场景下是一致的。
嵌套字段索引的统计
对于嵌套结构字段(如MetaData.userId),index_stats返回的统计同样有效,且测试覆盖了嵌套标量索引与嵌套向量索引的场景(python/python/tests/test_nested_fields.py、python/python/tests/test_nested_fields.py)。这也印证了indexStats传入的索引名(而非列名)是唯一标识,统计按索引维度聚合。
实战建议:用统计驱动索引维护
结合上述字段语义,推荐将indexStats纳入以下日常巡检流程:
- 建索引后立即校验:
numIndexedRows应等于表行数、numUnindexedRows为 0,否则说明建索引过程未完整覆盖(例如训练数据未覆盖新增分区)。 - 增量写入后监控:每次批量
add数据后比对numUnindexedRows是否增长,据此决定是否触发optimize()更新索引。 - 区分索引类型分支:判断
distanceType是否为undefined来区分向量索引与标量/FTS 索引,避免对不同类型索引做统一的假设。 - 处理 undefined 返回值:
indexStats对不存在的索引返回undefined,可作为"索引是否已创建"的探测手段,但注意与"索引存在但统计暂不可用"区分,必要时结合listIndices()交叉验证。
async function ensureIndexCoverage(table, indexName, expectedRows) { const stats = await table.indexStats(indexName); if (!stats) { console.warn(`索引 ${indexName} 不存在`); return; } const coverage = stats.numIndexedRows / (stats.numIndexedRows + stats.numUnindexedRows); console.log( `索引类型=${stats.indexType} 覆盖率=${(coverage * 100).toFixed(1)}% ` + `已索引=${stats.numIndexedRows} 未索引=${stats.numUnindexedRows} ` + `距离函数=${stats.distanceType ?? "N/A(非向量索引)"} 分片数=${stats.numIndices ?? "N/A"}` ); if (coverage < 1) { // 建议触发 optimize() 更新索引后再评估 console.warn(`索引 ${indexName} 尚未完全覆盖全部行`); } }小结
IndexStatistics虽然只有五个字段,却是理解 LanceDB 索引运行状态的最小完整视图:indexType告诉你索引是什么,numIndexedRows/numUnindexedRows告诉你覆盖是否完整,distanceType告诉你向量距离度量,numIndices告诉你分片规模。通过Table.indexStats(name)即可获取,返回undefined表示索引不存在。将其与createIndex、listIndices、optimize组合使用,即可构建一套完整的索引生命周期管理流程。本文字段语义均可在 nodejs/src/table.rs、rust/lancedb/src/index.rs 及相应测试用例中逐一验证。
- 向量数据库
- 数据库
- 人工智能
- 后端
【免费下载链接】lancedb
Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.
相关推荐
终极Android漫画阅读器:Mihon完整功能深度解析与使用指南
终极Android漫画阅读器:Mihon完整功能深度解析与使用指南 Mihon是一款免费开源的Android漫画阅读器应用,为用户提供完整的漫画、网络漫画和漫画
向量数据库数据库人工智能后端如何重新定义跨平台开发:hello-uniapp的技术架构演化路径
如何重新定义跨平台开发:hello uniapp的技术架构演化路径 在移动应用开发领域,跨平台框架长期面临性能损耗与原生体验的权衡困境。hello uniapp
向量数据库数据库人工智能后端envsafe实战教程:如何在Next.js项目中配置环境变量验证
envsafe实战教程:如何在Next.js项目中配置环境变量验证 envsafe是一个强大的环境变量验证工具,能确保你不会意外部署缺少或无效环境变量的应用。本
向量数据库数据库人工智能后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考