这算是第一篇向量检索的续集。上次内存炸了后,我专门花三天时间做了 VECTOR_MEMORY_SIZE 的参数矩阵测试,发现 Oracle 的文档在这个参数上写得云里雾里,什么"controls vector memory area",根本没说清这个 area 到底在 SGA 还是 PGA 里。
6.1 向量内存区的真实位置
通过 oradebug 转储 SGA 和 PGA 的 heapdump,我们发现 VECTOR_MEMORY_SIZE 分配的内存实际上横跨两个区域:HNSW 索引结构(邻居图)放在 SGA 的共享池里,因为多个会话要并发读;向量排序和距离计算的临时工作区放在 PGA 里,因为每个会话的查询向量不一样。所以 VECTOR_MEMORY_SIZE 既不是纯 SGA 参数,也不是纯 PGA 参数,它是个"跨区协调参数"。
具体来说,Oracle 内部把 VECTOR_MEMORY_SIZE 的值按 7:3 拆分:70% 从 SGA 的共享池分配(通过 kgh 堆分配器),30% 从 PGA 分配。如果 SGA 里共享池不够了,HNSW 索引构建会报 ORA-04031;如果 PGA 不够了,向量查询的排序会 spill 到临时表空间,延迟暴涨。
6.2 参数矩阵实验
-- 测试不同参数组合下的表现
ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 4G SCOPE=SPFILE;
ALTER SYSTEM SET PGA_AGGREGATE_TARGET = 8G SCOPE=SPFILE;
ALTER SYSTEM SET SGA_TARGET = 16G SCOPE=SPFILE;
STARTUP FORCE;
-- 监控向量内存使用
SELECT component, current_size, peak_size
FROM V$VECTOR_MEMORY;
-- COMPONENT = 'HNSW_INDEX' CURRENT_SIZE = 2.8G (SGA 部分)
-- COMPONENT = 'QUERY_WORKSPACE' CURRENT_SIZE = 1.2G (PGA 部分)
-- 模拟高并发查询
-- 50 个会话同时执行相似度搜索
-- 当 VECTOR_MEMORY_SIZE=4G 时,P95 延迟 45ms
-- 当 VECTOR_MEMORY_SIZE=8G 时,P95 延迟 22ms(PGA 工作区不再 spill)
-- 当 VECTOR_MEMORY_SIZE=12G 时,P95 延迟 21ms(边际效应递减)
我们的调参公式(针对 768 维向量、HNSW 索引):VECTOR_MEMORY_SIZE = (向量数量 * 维度 * 4 字节 * 1.5 倍开销) / 1024^3,然后向上取整到最近的 2GB 边界。比如 500 万条 768 维向量:5000000 * 768 * 4 * 1.5 = 23GB,所以 VECTOR_MEMORY_SIZE 至少设 24G,SGA 要相应配到 40G 以上。这个公式是我们自己测出来的,官方文档没给。