去年给客户做 AI 知识库方案选型,Oracle 26ai 的 AI Vector Search 被吹得很神,说什么"原生向量类型、不用外挂 Milvus"。我搭了个环境试了下,确实能跑,但跑到 800 万条 768 维向量的时候,PGA 直接飙到 28G,然后报 ORA-4030。这才发现 VECTOR_MEMORY_SIZE 这个参数的水很深。
1.1 向量索引不是普通的 B-Tree
Oracle 26ai 引入了 VECTOR 原生类型,支持 HNSW(图索引)和 IVF(倒排文件索引)两种算法。HNSW 在内存里建图,查询时走贪心最近邻搜索,优点是快,缺点是吃内存。IVF 先把向量空间切成 nlist 个簇,查询时只搜最近的几个簇,省内存但精度掉一点。
我们测下来的结论是:如果向量维度 ≤ 256,数据量 ≤ 100 万,HNSW 闭眼用;一旦维度上到 768(OpenAI 的 text-embedding-ada-002 就是这个维度),HNSW 的内存占用跟维度近似线性关系,这时候必须开 IVF,而且 nlist 要调到数据量的平方根附近。
1.2 实验过程:从 10 万到 1000 万的压测曲线
环境:Oracle 26ai EE,64G 内存,SGA 24G,PGA 12G。向量维度 768。
-- 建表
CREATE TABLE doc_vectors (
id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
doc_text VARCHAR2(4000),
vec VECTOR(768, float32)
);
-- 造数据:用 PL/SQL 批量插入随机向量
DECLARE
v_vec VECTOR(768, float32);
BEGIN
FOR i IN 1..1000000 LOOP
v_vec := VECTOR(
TO_VECTOR(UTL_RAW.CAST_TO_RAW(DBMS_RANDOM.STRING('X', 3072)), 768, float32)
);
INSERT INTO doc_vectors(doc_text, vec) VALUES ('doc'||i, v_vec);
IF MOD(i, 10000) = 0 THEN COMMIT; END IF;
END LOOP;
END;
/
-- 建 HNSW 索引
CREATE VECTOR INDEX idx_hnsw ON doc_vectors(vec)
ORGANIZATION INMEMORY
PARAMETERS 'type=hnsw, neighbors=64, efconstruction=128';
-- 查询时调整 efSearch
SELECT id, doc_text, cosine_distance(vec, :query_vec) dist
FROM doc_vectors
ORDER BY vec <-> :query_vec
FETCH FIRST 10 ROWS ONLY;
压测结果:10 万条时 HNSW 索引构建 12 秒,查询 P95 延迟 8ms;100 万条时构建 8 分钟,查询 P95 延迟 45ms;800 万条时构建过程中 PGA 涨到 28G,直接 ORA-04030。查了下 V$VECTOR_MEMORY,发现 HNSW 的邻居图结构每个节点存 64 个邻居指针,768 维 * 4 字节 + 指针开销,单个节点就要 3KB,800 万节点就是 24GB,这还没算 IVF 的 coarse quantizer。
1.3 VECTOR_MEMORY_SIZE 到底管什么
官方文档说 VECTOR_MEMORY_SIZE 控制"向量内存区",但我实测发现它其实是个软限制。真正硬限制的是 PGA_AGGREGATE_LIMIT。当向量计算需要排序或建图时,如果 VECTOR_MEMORY_SIZE 设小了,Oracle 会把部分数据 spill 到临时表空间,但 HNSW 索引构建是内存强相关的,spill 不了,只能硬报错。
我们的调参经验:VECTOR_MEMORY_SIZE = PGA_AGGREGATE_TARGET * 0.6,剩下 40% 给普通排序和哈希连接。如果机器内存吃紧,宁可把向量维度降到 512(用 PCA 降维),也别硬上 HNSW。另外,INMEMORY 表和向量索引会抢内存,建议把向量表单独放一个 INMEMORY MEMCOMPRESS FOR QUERY LOW 的区,别跟业务大表挤在一起。
最后说句得罪人的话:Oracle 的向量检索现阶段更适合做"企业知识库的内网搜索",也就是百万级文档、毫秒级响应的场景。如果非要跟 Elasticsearch 或 Milvus 比十亿级规模,那还是别自讨苦吃了,Oracle 的定价模型也不允许你这么玩。