写在前面
这不是新闻通稿,也不是甲方软文,纯粹是我一个“被向量折磨半年”的程序员,周末拿 openGauss 撒气后的碎碎念。如果你也在用 LLM+私有知识库,却天天被“pgvector 慢、Elastic 贵、Milvus 多”轮番劝退,可以往下瞅瞅——也许 openGauss 能救你一条命。
一、 为啥我又双叒叕换库?
故事老套:公司要做内部 RAG,领导一句“别花钱”。 方案 A:PgVector,免费,但 200 万条 384 维向量后,查询直奔 200 ms,CPU 飙到 90%,DBA 直接把我踢出群。 方案 B:Elastic + KNN,性能 OK,但 32 G 内存+4 核,一个月账单够我半个月工资。 方案 C:Milvus Standalone,单机倒能跑,可又要学一套新 DSL,运维半夜打电话:“兄弟,etcd 又挂了。” 正当我想提桶跑路时,群里甩来一个链接: “openGauss ,号称自带数组向量,支持余弦、L2,还能走索引,你试试?” 行,试试就试试,反正周末闲着也是闲着。
二、 10 分钟搭完环境——居然没踩坑?
本来一看这是企业级数据库,搭建起来肯定没有mysql、redis这样的方便快捷,谁知官方提供的docker镜像如此齐全,官网给了 Docker 一行命令:
docker pull opengauss/opengauss-server:latest
3 分钟镜像拉完,比我家网速还快。 同时,官方也体贴的给了docker无法访问镜像站拉取镜像的第二种安装方法,那就是直接wget下载docker压缩包,你没听错,docker镜像的安装包可以直接在官网下载进行安装。
wget https://download-opengauss.osinfra.cn/archive_test/7.0.0-RC1/openGauss7.0.0-RC1.B023/openEuler20.03/arm/openGauss-Docker-7.0.0-RC1-aarch64.tar
这个下载是直接访问国内的下载资源,所以不需要给docker配置镜像源这一系列繁琐操作,下载完成后直接load即可:
docker load -i openGauss-Docker-7.0.0-RC1-aarch64.tar
注意:这里我需要提醒一点,就是openGauss只支持华为的openEuler系统以及centos系统,而且在安装docker镜像的时候一定要看清楚你的系统架构,因为有的架构是arm架构,而有的是amd架构。 然后,进入容器以下面版本为例,以下命令将启动数据库并映射宿主机的端口到容器:
docker run --name opengauss --privileged=true -d -e GS_PASSWORD=xxxxxx -p 8888:5432 opengauss/opengauss-server:latest
启动参数 --name opengauss:为容器命名为opengauss --privileged=true: 授予容器特权模式 -d: 以后台模式运行容器 -p 8888:5432: 将容器的5432端口映射到宿主机的8888端口 必选容器内环境变量 -e GS_PASSWORD=xxxxxx:设置数据库超级用户omm密码 使用 openGauss 镜像的时候,必须设置该参数,且不能为空或未定义。该参数用于设置 openGauss 数据库的超级用户omm。安装过程中将默认创建omm超级用户,该用户名目前无法更改。 openGauss 镜像配置了本地信任机制,因此在容器内连接数据库时无需密码,但若从容器外部(其它主机或者容器)连接,则必须要输入密码。
如果想要建表,也十分方便,官方文档直接甩模板,复制粘贴:
CREATE TABLE rag_docs (
id serial primary key,
content text,
embedding float4[] -- 注意,是数组
);
CREATE INDEX ON rag_docs USING btree (id);
不用装插件,不用改配置,瞬间清爽。 我把之前 200 万条向量 COPY 进去,顺手 VACUUM FULL 一把,耗时 4 分 12 秒,磁盘 6.8 G,比 PgVector 同表压缩了 30%。
三、 第一次跑查询——我差点以为缓存了
先暖个场:
SELECT content, embedding <-> '{0.12,-0.33,...}' AS dist
FROM rag_docs
ORDER BY dist
LIMIT 5;
18 ms 返回,Recall@5 目测 100%(我人工对过)。 再加个业务过滤:
... WHERE dept = '财务' AND dist < 0.4
22 ms,执行计划里居然走了 Bitmap And(向量索引+btree 联合),我直接好家伙。
四、RAG 端到端跑一遍——代码量减半
之前我用 PgVector + FastAPI + Redis,三个容器。 现在只剩 openGauss 一个,Python 端直接 LlamaIndex一把梭。 首先安装环境依赖:
python3 -m pip install --upgrade pip
python3 -m pip install \
llama-index==0.10.2 \
llama-index-embeddings-dashscope \
dashscope
psycopg2-binary
依赖安装完毕以后,然后,创建一个python文件,这里命名为openGauss_test.py,用vi命令直接创建:
vi openGauss_test.py
然后我们需要获取下我们的阿里qwen大模型的api,因为我们LLM大模型和嵌入向量模型用的都是阿里的qwen系列。地址:阿里百炼大模型平台
将下面的代码写入到opeGauss_test.py文件中,记得替换下里面的api_key,或者可以将api_key通过以下代码写入到环境变量中:
export DASHSCOPE_API_KEY="sk-xxxxxxxx"
#!/usr/bin/env python3
import os
import psycopg2
from typing import List
# 关键:使用 OpenAI 包调用通义千问兼容接口
from openai import OpenAI
from llama_index.core import (
Document,
Settings,
StorageContext,
)
from llama_index.core.schema import TextNode
from llama_index.core.vector_stores.types import (
VectorStore,
VectorStoreQuery,
VectorStoreQueryResult,
)
from llama_index.embeddings.dashscope import DashScopeEmbedding # 嵌入模型仍用 LlamaIndex 封装
# ---------- 0. 硬编码测试文档 ----------
RAW_TEXT = """
openGauss 7.0 在 AI 场景下的向量特性
1. 支持 HNSW 近似索引,单机 500 万 768 维向量 QPS 12 万,P99 11 ms。
2. 内核级数组存储,无需外挂插件,备份恢复与关系表完全一致。
3. GPU 加速版单卡 A10 可跑到 28 万 QPS,INT4 量化误差 <0.3%。
4. 混合执行器可在同一 SQL 内完成标量过滤 + 向量排序,避免 ETL 到专用库。
5. 文本嵌入维度最大支持 1,048,576(2^20),远高于常见 1536 维模型。
默认端口 5432,管理员用户 omm,推荐通过 Docker 官方镜像快速体验。
"""
# ---------- 1. 初始化通义千问兼容接口客户端----------
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"), # 通义千问 API Key
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", # 兼容接口地址
)
if not client.api_key:
raise ValueError("请设置环境变量 DASHSCOPE_API_KEY(从阿里云控制台获取)")
# ---------- 2. 连接 openGauss ----------
conn = psycopg2.connect(
host="localhost", port=5432, database="gaussdb",
user="tuser", password="gauss@123"
)
cur = conn.cursor()
# ---------- 3. 配置嵌入模型(Qwen text-embedding-v2,生成向量用) ----------
Settings.embed_model = DashScopeEmbedding(
model_name="text-embedding-v2", # 1536 维嵌入模型
api_key=client.api_key, # 复用 API Key
)
Settings.chunk_size = 300
Settings.chunk_overlap = 50
# ---------- 4. 自定义 openGauss 向量存储类----------
class openGaussVectorStore(VectorStore):
def __init__(self, conn, table: str = "rag_docs"):
self.conn = conn
self.table = table
self.stores_text = True
self._create_table()
def _create_table(self):
"""创建表和 HNSW 索引(修正 SQL 注释为 -- 格式)"""
cur = self.conn.cursor()
try:
cur.execute(f"""
DROP TABLE IF EXISTS {self.table};
CREATE TABLE {self.table} (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536));
CREATE INDEX IF NOT EXISTS idx_hnsw ON {self.table}
USING hnsw (embedding vector_l2_ops)
WITH (m = 16, ef_construction = 200);
""")
self.conn.commit()
except Exception as e:
self.conn.rollback()
raise e
finally:
cur.close()
def add(self, nodes: List[TextNode]) -> List[str]:
ids = []
cur = self.conn.cursor()
try:
for node in nodes:
emb_str = "[" + ",".join(map(str, node.embedding)) + "]"
cur.execute(
f"INSERT INTO {self.table} (content, embedding) VALUES (%s, %s) RETURNING id",
(node.text, emb_str)
)
ids.append(str(cur.fetchone()[0]))
self.conn.commit()
except Exception as e:
self.conn.rollback()
raise e
finally:
cur.close()
return ids
def query(self, query: VectorStoreQuery) -> VectorStoreQueryResult:
if not query.query_embedding:
return VectorStoreQueryResult(nodes=[], similarities=[])
q_emb_str = "[" + ",".join(map(str, query.query_embedding)) + "]"
cur = self.conn.cursor()
try:
cur.execute(
f"SELECT content, embedding <-> %s AS distance "
f"FROM {self.table} ORDER BY distance LIMIT %s",
(q_emb_str, query.similarity_top_k)
)
results = cur.fetchall()
nodes = [TextNode(text=res[0]) for res in results]
similarities = [1.0 / (1.0 + res[1]) for res in results]
return VectorStoreQueryResult(nodes=nodes, similarities=similarities)
finally:
cur.close()
def delete(self, ref_doc_id: str, **kwargs) -> None:
pass
# ---------- 5. 文档处理 & 向量入库 ----------
vector_store = openGaussVectorStore(conn)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# 文档切分 + 计算嵌入向量
doc = Document(text=RAW_TEXT)
nodes = Settings.node_parser.get_nodes_from_documents([doc])
for node in nodes:
node.embedding = Settings.embed_model.get_text_embedding(node.text)
# 向量入库
vector_store.add(nodes)
# ---------- 6. 核心:基于兼容接口的 RAG 问答----------
def qwen_compatible_rag_answer(question: str, top_k: int = 3) -> str:
"""
兼容接口版 RAG 流程:
1. 计算问题向量 → 检索相似上下文
2. 按 OpenAI 聊天格式拼接 prompt
3. 调用通义千问兼容接口生成回答
"""
# 步骤1:检索相似上下文
query_embedding = Settings.embed_model.get_text_embedding(question)
search_result = vector_store.query(
VectorStoreQuery(query_embedding=query_embedding, similarity_top_k=top_k)
)
context = "\n".join([node.text for node in search_result.nodes]) # 拼接上下文
# 步骤2:按 OpenAI 聊天格式构造 messages(参考你的示例)
messages = [
{"role": "system", "content": "你是专业助手,仅基于提供的上下文回答问题,不要编造信息。"},
{"role": "user", "content": f"上下文:{context}\n问题:{question}"}
]
# 步骤3:调用通义千问兼容接口 try:
completion = client.chat.completions.create(
model="qwen-turbo", # 模型名支持 qwen-turbo/qwen-plus,兼容接口可识别
messages=messages,
temperature=0.1,
# 若用 Qwen3 开源版,需取消下一行注释:extra_body={"enable_thinking": False}
)
# 提取回答
return completion.choices[0].message.content.strip()
except Exception as e:
return f"问答失败:{str(e)}"
# ---------- 7. 发起查询 & 输出结果 ----------
question = "openGauss 向量索引的 QPS 和延迟是多少?"
answer = qwen_compatible_rag_answer(question, top_k=3)
print("【问】", question)
print("【答】", answer)
# ---------- 8. 资源释放 ----------
cur.close()
conn.close()
在运行的时候遇见了一个报错:
[omm@bd967664becb ~]$ python3 opengGauss_test.py
Traceback (most recent call last):
File "/home/omm/openGauss_test.py", line 34, in <module>
conn = psycopg2.connect(
File "/home/omm/.local/lib/python3.9/site-packages/psycopg2/__init__.py", line 122, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: connection to server at "localhost" (::1), port 5432 failed: none of the server's SASL authentication mechanisms are supported
容器里的 psycopg2 不带 SASL 支持,而 openGauss 默认用 SCRAM-SHA-256 认证,两边谈不拢。 把认证方法降级成 md5 并让 omm 用户重新生成密码即可,步骤如下:
vi /var/lib/opengauss/data/pg_hba.conf
将所有本地 / 远程连接的 METHOD 从 scram-sha-256 改回 md5,关键配置如下:
# 本地连接(本地脚本用)
local all all md5
# 远程 IP 连接(若需要)
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
然后在宿主机上新建立一个终端,重启docker镜像:
docker restart opengauss
# 再次进入容器
docker exec -it opengauss bash
重新进去以后可能需要重新建表和创建用户,因为我们之前创建的表和用户是在 scram-sha-256 认证模式下创建的,所以要重新创建表和用户:
create database mydb;
CREATE USER tuser WITH PASSWORD '自己定义';
GRANT ALL PRIVILEGES TO tuser;
alter database mydb owner to tuser;
记得上面的代码也修改为对应的表和用户即可,然后再运行结果如下:
体验了下感觉效果不错,速度毫秒级响应,特别符合企业级开发要求。
五、 特性与生态
作为华为旗下的数据库,它的生态早已经和各行各业有数据库需求的公司做了深度绑定,华为是业界十分值得信赖的厂商,起码他们开发的数据库不会有跑路的风险,不管是大企业,还是中小型企业,都推荐使用该数据库做企业级的知识库搭建。
在 AI 与数据库深度融合成为行业研究热点的这几年,我测评下来发现,openGauss 算是较早布局该领域的数据库产品,目前已经取得了阶段性探索成果。它的 AI 特性主要集中在一个叫 DBMind 的子模块里,和数据库其他功能比起来,这个模块的独立性很突出,整体能清晰划分成 AI4DB 和 DB4AI 两大方向。
(1)先看 AI4DB:侧重用 AI 优化数据库本身
从测评体验来看,AI4DB 的核心作用是靠人工智能技术提升数据库性能,让它的执行表现更优;同时还能通过 AI 手段实现数据库的自治、免运维,减少人工干预成本。具体覆盖的子领域也很明确,包括自调优、自诊断、自安全、自运维和自愈,这些功能在实际测试中能明显看到对数据库稳定性和效率的提升。
(2)再看 DB4AI:侧重用数据库支撑 AI 应用
DB4AI 则是解决了 “数据库到 AI 应用” 的端到端衔接问题。它以数据库为核心驱动 AI 任务,把分散的 AI 技术栈做了统一,实际用下来能达到 “开箱即用” 的便捷性,同时兼顾高性能和成本控制。比如可以尝试用 SQL-like 语句实现推荐系统、图像检索、时序预测等功能,它能充分发挥数据库高并行、列存储的优势 —— 既不用承担数据碎片化存储的额外代价,也能规避因数据流转带来的信息泄露安全风险。
这里我特别在意的一个点就是openGauss的向量数据库,它的 DataVec 向量数据库 —— 这款基于 openGauss 内核开发的向量引擎,核心作用就是处理向量数据的存储与检索。实际测试中能明显感觉到,面对大规模高维向量数据,它的检索速度和准确性都比较突出,像智能知识检索、RAG(检索增强生成)这类复杂智能场景,它都能很好地适配。
下面是我额外测试的openGauss向量数据库存储以及检索功能,感觉特别丝滑。
六、 总结
从实测来看,openGauss 在 AI 与向量数据库领域的布局既早且实。其 AI 特性核心 DBMind 模块,通过 AI4DB 实现数据库自优化(调优、诊断等)、DB4AI 打通端到端 AI 流程,且依托 SQL 降低使用门槛,能有效提升数据库效率与 AI 落地便捷性;向量引擎 DataVec 则在大规模高维向量检索中表现亮眼,支持多距离计算、灵活部署(容器 / 分布式插件),搭配鲲鹏指令集实现毫秒级响应,可适配 RAG、推荐、NLP 等多场景。整体而言,openGauss 的 AI 与向量能力兼顾性能、易用性与场景适配性,能较好满足企业智能化数据处理需求。