RAG分页检索,海量知识库分片查询,避免一次加载过多文档

当知识库里的文档达到几十万甚至上百万条时,RAG 系统如果一次性把所有文档加载到内存里做向量化或召回,轻则查询变慢,重则直接把服务拖崩。
RAG 分页检索的思路是每次只读取一个小批次,配合分片查询把海量数据拆成多个区间处理,从源头避免内存和性能压力。
本文就用一个零基础能跟上的方式,讲清适用场景、实现方法和常见坑。

什么情况下必须做分页检索和分片查询

如果你的 RAG 服务出现以下现象,就说明需要引入分页检索或分片查询了:

  • 启动或建索引时内存占用持续暴涨,甚至触发 OOM。
  • 用户问一个问题,系统要把整个知识库扫一遍才能返回结果。
  • 批量导入文档时,一次性读取全部内容导致接口超时。
  • 向量数据库在查询时因为返回数量过大而响应缓慢。

分页解决的是“一次不要取太多结果”的问题,分片解决的是“如何把大任务拆成小任务并行处理”的问题。
两者配合,才能让海量知识库稳定运行。

环境准备与基础思路

动手之前,先确认你的 RAG 项目里已经安装了向量数据库客户端,比如 Chroma、FAISS、Elasticsearch 或 Milvus。
代码层面只需要确保能执行两件事:

  • 支持带偏移量的查询(或基于游标的查询)。
  • 支持按某个字段做条件过滤。

下面以 Python 伪代码演示,实际使用时把函数名替换成你所用的数据库 API 即可。
核心思路是先定义每批读取的条数,再用循环逐批处理,直到全部读完。

分页检索的两种常用写法

最简单的写法是 limit + offset,适合数据量在十万级以内的场景:

batch_size = 100
offset = 0
while True:
    # 假设这是你的向量数据库查询接口
    docs = query_knowledge_db(collection="knowledge", limit=batch_size, offset=offset)
    if not docs:
        break
    process_docs(docs)  # 做向量化、回答或过滤
    offset += batch_size

这段代码每次只取 100 条,处理完后再取下一批。offset 不断累加,直到返回为空。

offset 越大,数据库需要跳过的行就越多,当偏移量到几万时性能会明显下降。
更推荐用游标分页,很多数据库支持按 ID 或时间戳范围定位:

last_id = None
batch_size = 100
while True:
    if last_id is None:
        docs = query_knowledge_db(collection="knowledge", limit=batch_size)
    else:
        docs = query_knowledge_db(collection="knowledge", limit=batch_size, after=last_id)
    if not docs:
        break
    process_docs(docs)
    last_id = docs[-1]["id"]  # 每批取最后一条的ID作为下一批起点

游标分页不存在“跳过大段数据”的成本,深层分页时性能更稳定。
如果你的向量库支持 aftersearch_after 参数,优先用这种方式。

海量知识库分片查询策略

分页解决了单次读取量的问题,但全表扫描本身也很慢。
分片查询可以把知识库切成多个互不重叠的区间,比如按文档 ID 范围、按创建时间、按文档类型。

下面是一个按 ID 区间分片的示例:

start_id = 0
batch_size = 5000
max_id = get_max_id("docs")
while start_id < max_id:
    end_id = min(start_id + batch_size, max_id)
    docs = query_knowledge_db("SELECT * FROM docs WHERE id >= ? AND id < ?", (start_id, end_id))
    process_docs(docs)
    start_id = end_id

按时间分片同理,比如按月份处理:

for month in ["2024-01", "2024-02", "2024-03"]:
    docs = query_knowledge_db(collection="knowledge", filter={"month": month})
    process_docs(docs)

分片粒度建议根据单批次处理耗时来定。
如果一批 5000 条处理要 5 秒,说明粒度偏大,可以适当减小;
如果处理太快,可能是粒度太小导致循环次数过多。

避坑与验证方法

实操中这几个问题最容易踩,提前注意能省不少时间:

  • 不要无脑调大 limit。一次加载多看起来效率高,但内存峰值会成倍上涨,尤其是需要把文档内容转换成向量时。合理值建议从 64 或 128 开始测试。
  • 注意数据一致性。如果分片查询期间知识库还在写入新文档,可能造成重复或漏读。建议先暂停写入,或者按快照时间过滤。
  • 分页参数别用 float。很多数据库要求整数,Python 中 limit=100.0 会直接报错,先用 int() 包一层。
  • 超时时间要留够。批量处理比单条查询慢,接口和客户端都要把超时调大,比如从 10 秒改成 60 秒。

验证分页和分片是否生效,重点看三个指标:

  1. 进程内存占用是否保持平稳,不会随扫描进度持续飙升。
  2. 每次处理完一批后,内存曲线会回落到接近初始值。
  3. 同一批数据重复处理时,结果数量一致,没有遗漏或重复。

最简单的方式是在处理函数里打印 batch_indexlen(docs),跑到最后一批时确认总条数等于知识库总数。

如果你正在处理 RAG 分页检索和知识库分片查询,建议先按本文的循环模式写一版最小示例,用 1 万条测试数据跑通,再逐步扩大到全量。
遇到性能下降时,优先检查是不是分页深度太大导致扫描变慢,必要时换成游标分页或缩小分片粒度,多数问题都能在不动架构的情况下解决。

分享到:
上一篇
RAG生产遇到内存泄漏,长时间运行向量服务重启策略
下一篇
向量库迁移工具,不同向量数据库之间数据迁移实操
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意