凌晨三点,新部署的RAG服务上线。测试全绿,p99检索耗时40毫秒,仪表盘一片健康。然后第一个用户查询来了——8秒后才返回。第二个同样查询:38毫秒。代码没变,索引没变,查询语句一模一样。Grafana上每次滚动部署都出现一道尖刺,值班工程师耸耸肩说"反正很快恢复"。
这不是"很快恢复"能糊弄过去的事。这道尖刺是索引在逐页从磁盘读取数据,用户就盯着加载动画干等。安静的早晨是一个 frustrated 用户,黑五促销时就是几千个用户同时命中刚重启的Pod,排队等待同样的页错误。
![]()
这篇文章拆解冷启动税的本质:HNSW索引为何等到首次查询才真正加载,pgvector、Qdrant、Pinecone的真实数据表现,以及四种预热模式如何让用户永远看不到这道尖刺。
HNSW(分层可导航小世界)索引本质上是一张图。每个向量是一个节点,节点在多层有邻居链接,查询从顶层入口点逐层向下遍历,k=10搜索通常访问几百个节点。图数据以内存映射文件或分段形式存于磁盘,向量数据通常紧邻图存储。
进程启动时不会把整个索引读入内存。它打开文件,请求内核做内存映射,启动工作就此结束。页面只在被访问时才读入,而"被访问"的时刻就是首次查询。
首次查询遍历图结构。每条邻居指针触发一次页错误,每个向量评分再触发向量数据的页错误。现代NVMe很快,但页错误仍需50-150微秒(典型NVMe随机读取延迟),单次HNSW搜索可能触及数百个页面:图页面、向量页面、载荷页面。简单乘法:几百次页错误×约100微秒,仅查找就耗去数十毫秒,再加上实际计算和嵌入端的额外冷路径开销。
这是单次查询的账。首次查询还要支付几项一次性设置成本:线程池预热、JIT内核选择、分配器初始化。单独看都不贵,堆在同一条请求上就难看了。
标题里的8秒是上限值,来自500万向量pgvector索引配合冷页缓存和较慢SATA SSD的场景;下一节的基准测试在更快NVMe上复现了4.8秒的数据点。新鲜容器加冷页缓存,首次查询通常落在3-10秒区间,取决于磁盘速度和数据集规模。Qdrant的磁盘分段架构文档显示类似区间,Pinecone Serverless的冷启动则因层级而异。模式一致:工作被推迟了,总得有人买单。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.