这类问题我又碰上了一次。在本地用 lancedb 0.15.0 的 Python SDK 建索引,表里 4800 行 1024 维向量,table.create_index(metric="cosine", num_partitions=256, num_sub_vectors=64) 直接抛 RuntimeError: Not enough rows to train PQ, need 256 rows per partition,把 num_partitions 降到 8 后错误照旧,换成 IVF_FLAT 才有反应。

第一反应是「建索引前表里混着空向量,被过滤后有效行更少」,验证下来不成立。

排查方向其实有限,先把可能性排一排。PQ 训练要求每个分区至少 256 条样本,行数不够;num_sub_vectors 太大,单段维度除不尽导致训练直接跳过;索引名沿用了上一次失败的记录,代码读到的还是旧索引。

动手时先确认表里真实行数与向量维度

python -c "import lancedb;db=lancedb.connect('./lance_db');t=db.open_table('docs');print(t.count_rows(), t.schema)"

然后把分区数按 行数除以 256 重算,不够就退回暴力检索

python -c "print(4800//256)"

空向量先刷掉再统计有效行

python -c "import lancedb;t=lancedb.connect('./lance_db').open_table('docs');print(t.count_rows('vector is not null'))"

末了用 replace 重建索引并指定更小的子向量数

python -c "import lancedb;lancedb.connect('./lance_db').open_table('docs').create_index(metric='cosine', num_partitions=18, num_sub_vectors=32, replace=True)"

恢复的判定其实很直接。create_index 返回成功,list_indices 里能看到 IVF_PQ,检索十条的 _distance 单调递增,不再出现 Not enough rows。

索引训练是抽样过程,建之前先用分区数乘以 256 算出样本底线,低于这个数就老实退回 IVF_FLAT 或者暴力检索,硬调参数只会把时间浪费在报错上。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189