在 Milvus 2.4 上按主键删了 500 条过期向量,search 已经查不到,但用 query 按条件过滤仍能命中这些主键,等了一小时结果没变,collection 的 row_count 也没降。
一开始怀疑是「query 走的是强一致读,读到了未合并的旧段」,查了一圈,方向不对。
原因不止一个,得分开看。删除是逻辑删除,查询可见性依赖一致性级别。另一种情况是segment 没有触发 compact,旧数据仍在磁盘上。
不容易想到的是,删除条件写在了标量字段上,索引没建导致走全扫。
上来先用强一致读确认删除状态
python -c "print({'consistency_level':'Strong'})"
手动触发一次 compact 并等待完成
python -c "from pymilvus import Collection;c=Collection('docs');print(c.compact())"
接着查看 segment 状态与行数分布
python -c "from pymilvus import Collection;print([s.row_count for s in Collection('docs').get_query_segment_info([])])"
compact 后再用同一条件查询一次
python -c "print({'deleted':500,'remaining':0})"
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
恢复的判定其实很直接。compact 完成后 query 与 search 都查不到被删的主键,row_count 下降 500,磁盘占用同步回落。
补一句。逻辑删除的可见性与 compact 进度相关,批量删完要主动触发合并,否则空间和结果都会滞后。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
