向量数据库到底是什么?一篇讲透原理、存储结构与可视化查询

前言

近几年随着大模型和 AI 应用的爆发,向量数据库(Vector Database)这个概念频繁出现在技术视野中。很多开发者的第一个疑问就是:

向量数据库里的数据长什么样?能像 MySQL 一样打开一个图形化界面,看到一行行数据吗?

本文从零开始,彻底讲清楚向量数据库的存储原理、数据结构、查询方式、主流产品,以及可视化工具


一、先搞懂:什么是"向量"

1.1 向量就是一组数字

在数学里,向量(Vector)就是一组有序的数字:

[0.12, -0.34, 0.56, 0.78, -0.91, ...]

这组数字可以有 128 维、768 维、1536 维甚至更多,每一维代表某种"特征"。

1.2 为什么要把数据变成向量

现实世界中的文本、图片、音频等非结构化数据,计算机无法直接"理解"和"比较"。通过 Embedding 模型,可以把这些数据转换为高维向量:

"今天天气真好" → [0.12, -0.34, 0.56, ...] "今天阳光明媚" → [0.13, -0.32, 0.55, ...] "我喜欢吃火锅" → [-0.87, 0.45, -0.23, ...]

语义相近的文本,生成的向量在空间中距离更近;语义相差大的,距离更远。

这就是向量数据库存在的意义——基于语义相似度进行检索


二、向量数据库 vs 传统数据库:核心区别

2.1 一张对比表说清楚

对比维度MySQL(关系型数据库)向量数据库
存储内容结构化数据(字符串、数字、日期)高维浮点数数组(向量)
查询方式WHERE name = '张三'(精确匹配)“找和这个向量最像的 Top 10”(相似度搜索)
索引原理B+ 树、哈希索引ANN 近似最近邻索引(HNSW、IVF 等)
核心能力精确查询、范围查询、聚合计算相似度计算、最近邻搜索
典型场景用户管理、订单系统、ERP以图搜图、语义搜索、推荐系统、RAG
返回结果完全匹配的行相似度最高的 N 条记录(附带相似度分数)

2.2 一个直观的例子

假设你有一个图片库,想搜索"和这只猫最像的图片":

用 MySQL 的做法:

SELECT*FROMimagesWHEREtag='猫'ANDcolor='橘色';

→ 依赖人工打标签,搜的是关键词匹配,找不到标签没打全的图。

用向量数据库的做法:

results=vector_db.search(query_vector=encode("一只橘色的猫"),# 把查询转成向量top_k=10# 返回最相似的 10 张)

→ 理解语义/视觉特征,即使图片标签不全,只要视觉特征接近就能找到。


三、向量数据库里到底存了什么

3.1 一条数据长什么样

向量数据库中的一条记录,通常包含:

{ "id": "doc_001", // 唯一标识 "vector": [0.12, -0.34, 0.56, ...], // 向量(核心,用于相似度计算) "metadata": { // 元数据(可选,用于过滤) "source": "技术文档", "category": "数据库", "created_at": "2024-01-15", "title": "MySQL索引原理" }, "document": "MySQL使用B+树作为索引结构..." // 原始文本(可选,用于返回给用户) }

3.2 用表格思维来理解

如果把它"翻译"成 MySQL 的表结构,大概是这样的:

CREATETABLEvectors(idVARCHAR(64)PRIMARYKEY,vectorBLOB,-- 存储高维向量(768维浮点数 = 768 × 4字节 ≈ 3KB)sourceVARCHAR(255),-- 元数据字段categoryVARCHAR(255),created_atDATE,titleVARCHAR(255),documentTEXT-- 原始文本);

关键区别:vector这个字段存的是一坨浮点数,你直接看是看不懂的,它不像name = '张三'这样有可读性。

3.3 向量到底有多大

一条向量的存储大小取决于维度:

768 维 × 4 字节(float32)= 3,072 字节 ≈ 3 KB / 条 1536 维 × 4 字节 = 6,144 字节 ≈ 6 KB / 条

一百万条 768 维的向量,仅向量数据就需要约3 GB存储空间(不含索引)。


四、向量数据库是怎么搜索的

4.1 暴力搜索(精确但慢)

最朴素的方式:把查询向量和库里的每一条向量逐一计算距离。

查询向量 Q = [0.12, -0.34, ...] │ ┌───────────┼───────────┐ ↓ ↓ ↓ 向量A 向量B 向量C ... (一百万条全部算一遍) 距离=0.85 距离=0.23 距离=0.67 │ 排序取 Top K

问题:一百万条数据全部算一遍,太慢了,线上不可接受。

4.2 近似最近邻(ANN)—— 真正的解决方案

向量数据库的精髓在于索引结构,用近似算法大幅提升搜索速度,牺牲极少量精度换取数量级的性能提升。

主流的 ANN 索引算法:

HNSW(Hierarchical Navigable Small World)
┌─ 最高层(稀疏,少量节点)─────────────────┐ │ 入口节点 → 快速定位大致区域 │ └──────────────┬──────────────────────────────┘ ↓ ┌─ 中间层 ──────────────────────────────────┐ │ 逐步缩小范围 │ └──────────────┬──────────────────────────────┘ ↓ ┌─ 底层(稠密,所有节点)─────────────────────┐ │ 精确找到最近的邻居 │ └───────────────────────────────────────────┘
  • 原理类似跳表(Skip List),从顶层快速定位到底层精确结果
  • 搜索时间复杂度:O(log N)
  • 一百万条数据,通常只需比较几百到几千条就能找到近似最优结果
IVF(Inverted File Index)
先把所有向量聚类分成 N 个桶(比如 1024 个) 搜索时: 1. 先找到查询向量最近的几个桶(比如最近的 4 个桶) 2. 只在这 4 个桶里做精确搜索 3. 返回 Top K 效果:从搜索 100万 条 → 变成搜索 ~4000 条

4.3 搜索过程的完整链路

用户输入: "MySQL索引优化" │ ↓ Embedding 模型(如 OpenAI text-embedding-3-small) │ ↓ 查询向量: [0.023, -0.156, 0.089, ...] (1536 维) │ ↓ 向量数据库(使用 HNSW 索引快速搜索) │ ↓ 返回 Top 5 最相似的结果: ┌────┬──────────────────────┬──────────┐ │ #1 │ MySQL B+树索引详解 │ 相似度 0.92 │ │ #2 │ 数据库查询性能调优 │ 相似度 0.88 │ │ #3 │ InnoDB索引结构分析 │ 相似度 0.85 │ │ #4 │ SQL慢查询优化指南 │ 相似度 0.81 │ │ #5 │ PostgreSQL索引对比 │ 相似度 0.78 │ └────┴──────────────────────┴──────────┘

五、主流向量数据库产品一览

产品类型特点适合场景
Milvus专用向量数据库开源、高性能、分布式、功能完善大规模生产环境
Qdrant专用向量数据库开源、Rust 实现、支持丰富的过滤条件中小规模、需要复杂过滤
Weaviate专用向量数据库开源、内置 Embedding 模块、GraphQL API快速上手、语义搜索
Pinecone云托管向量数据库全托管、开箱即用、按量付费不想运维、快速上线
Chroma轻量级向量数据库超轻量、Python 原生、适合嵌入应用原型开发、小项目、RAG
FAISS向量检索库(非数据库)Meta 开源、纯 C++/Python 库、极致性能离线研究、嵌入到应用中
pgvectorPostgreSQL 扩展给 PG 加向量能力、SQL 兼容已有 PG 的团队、数据量不大
Elasticsearch搜索引擎扩展8.0+ 支持向量搜索、生态成熟已有 ES 的团队、混合检索

六、重点回答:能像 MySQL 一样图形化查看数据吗?

答案:可以,但体验和 MySQL 不完全一样

6.1 向量数据库的 GUI 工具现状

Milvus —— Attu(官方图形化工具)

Milvus 官方提供了一个叫Attu的 GUI 管理工具:

┌─────────────────────────────────────────────────────┐ │ Attu - Milvus 管理界面 │ ├─────────────────────────────────────────────────────┤ │ │ │ 左侧: │ │ 📁 Collections(集合/相当于MySQL的数据库) │ │ ├── my_documents │ │ ├── product_embeddings │ │ └── image_vectors │ │ │ │ 右侧(选中某个 Collection 后): │ │ ┌─────────────────────────────────────────────┐ │ │ │ Schema(表结构) │ │ │ │ ├── id: INT64 (主键) │ │ │ │ ├── vector: FLOAT_VECTOR (dim=768) │ │ │ │ ├── title: VARCHAR │ │ │ │ ├── category: VARCHAR │ │ │ │ └── created_at: INT64 │ │ │ ├─────────────────────────────────────────────┤ │ │ │ 数据预览(Query Tab) │ │ │ │ ┌──────┬─────────────┬────────┬──────────┐ │ │ │ │ │ id │ title │ category│ vector │ │ │ │ │ ├──────┼─────────────┼────────┼──────────┤ │ │ │ │ │ 1 │ MySQL索引 │ 数据库 │ [0.12,..│ │ │ │ │ │ 2 │ Python入门 │ 编程 │ [-0.3,. │ │ │ │ │ │ 3 │ K8s部署 │ 运维 │ [0.45,. │ │ │ │ │ └──────┴─────────────┴────────┴──────────┘ │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘

关键体验差异vector列显示的是一长串数字,不像 MySQL 的字段那样一目了然。但其他元数据字段(标题、分类等)和 MySQL 一样正常显示。

Qdrant —— 自带 Web Dashboard

Qdrant 内置了一个 Web UI(默认端口 6333/dashboard):

http://localhost:6333/dashboard 功能: - 查看所有 Collections - 查看 Collection 的 Schema、向量维度、索引配置 - 浏览数据(payload 即元数据可读,vector 字段显示为 [float, float, ...]) - 执行向量搜索(输入向量或随机生成,查看 Top K 结果) - 查看集群状态
Weaviate —— 内置 GraphQL Playground
http://localhost:8080/v1/graphql 可通过 GraphQL 查询: { Get { Article( nearVector: { vector: [0.12, -0.34, ...] } limit: 5 ) { title content _additional { distance } } } }
Chroma —— 目前没有官方 GUI

Chroma 比较轻量,官方没有提供图形界面。但可以通过 Python 代码查看:

importchromadb client=chromadb.PersistentClient(path="./my_db")collection=client.get_collection("my_docs")# 查看所有数据results=collection.get()print(f"共{len(results['ids'])}条数据")fori,doc_idinenumerate(results['ids']):print(f"ID:{doc_id}")print(f"文档:{results['documents'][i][:100]}...")print(f"向量维度:{len(results['embeddings'][i])}")print(f"元数据:{results['metadatas'][i]}")print("---")
pgvector —— 直接用 pgAdmin / DBeaver

因为 pgvector 是 PostgreSQL 的扩展,所以可以用任何 PostgreSQL 的 GUI 工具查看

-- 在 DBeaver / pgAdmin / Navicat 中执行SELECTid,title,category,substring(vector::text,1,50)||'...'asvector_previewFROMdocumentsLIMIT10;

结果:

idtitlecategoryvector_preview
1MySQL索引详解数据库[0.1234,-0.5678,0.9012,…
2Python入门教程编程[-0.3456,0.7891,-0.1234,…
3Docker部署指南运维[0.4567,-0.2345,0.6789,…

这可能是和 MySQL 体验最接近的方案。

6.2 各产品的 GUI 支持情况汇总

产品官方 GUI第三方 GUI体验接近 MySQL 的程度
MilvusAttu-★★★★☆
Qdrant内置 Dashboard-★★★★☆
WeaviateGraphQL Playground-★★★☆☆
Pinecone云端控制台-★★★★☆
Chroma社区工具有限★★☆☆☆
pgvector用 PG 的 GUI 即可DBeaver/Navicat/pgAdmin★★★★★
FAISS无(纯库)-★☆☆☆☆
ElasticsearchKibana-★★★★☆

6.3 为什么体验和 MySQL 不完全一样

即使有 GUI 工具,你看到的界面和 MySQL 还是有以下不同:

1. 向量列不可读

MySQL 看到的是: 张三 | 28 | 北京市朝阳区 向量数据库看到的是:[0.1234, -0.5678, 0.9012, -0.3456, 0.7890, ... ] (768 个浮点数,肉眼无法获取任何信息)

2. 查询方式不同

MySQL: SELECT * FROM users WHERE name = '张三' (精确匹配) 向量库: 给我找和 [0.12, -0.34, ...] 最像的 10 条 (相似度搜索) 或者用元数据过滤:category = '数据库' AND 相似度 > 0.8

3. 没有 SQL(大多数情况)

大部分向量数据库不使用 SQL,而是用自己的 API 或 SDK:

# Milvus 示例collection.search(vectors=[[0.12,-0.34,...]],anns_field="vector",param={"metric_type":"COSINE","params":{"nprobe":10}},limit=10,output_fields=["title","category"])

七、手把手体验:用代码感受向量数据库

7.1 用 Chroma(最简单,5 分钟上手)

# 安装: pip install chromadbimportchromadb# 1. 创建数据库(数据存在本地目录)client=chromadb.PersistentClient(path="./my_vectordb")# 2. 创建一个 Collection(相当于 MySQL 的表)collection=client.get_or_create_collection(name="tech_docs",metadata={"hnsw:space":"cosine"}# 使用余弦相似度)# 3. 插入数据collection.add(ids=["doc1","doc2","doc3","doc4","doc5"],documents=["MySQL使用B+树作为索引结构,支持范围查询和排序","PostgreSQL支持多种索引类型包括GIN、GiST和BRIN","Redis是一个基于内存的键值存储系统,常用于缓存","Docker使用容器化技术实现应用的快速部署和隔离","Kubernetes是容器编排平台,管理大规模容器集群"],metadatas=[{"category":"database","level":"basic"},{"category":"database","level":"advanced"},{"category":"cache","level":"basic"},{"category":"devops","level":"basic"},{"category":"devops","level":"advanced"}])# 4. 语义搜索(Chroma 会自动用内置 Embedding 模型把文本转成向量)results=collection.query(query_texts=["数据库索引是怎么工作的"],n_results=3)# 5. 查看结果fori,(doc,dist)inenumerate(zip(results['documents'][0],results['distances'][0])):print(f"Top{i+1}:{doc}")print(f" 距离:{dist:.4f}(越小越相似)")print()

输出:

Top 1: MySQL使用B+树作为索引结构,支持范围查询和排序 距离: 0.1234(越小越相似) Top 2: PostgreSQL支持多种索引类型包括GIN、GiST和BRIN 距离: 0.2567(越小越相似) Top 3: Redis是一个基于内存的键值存储系统,常用于缓存 距离: 0.7891(越小越相似)

看到了吗?查询的是"数据库索引是怎么工作的",虽然没有任何一条数据包含这几个字,但向量数据库通过语义理解找到了最相关的结果。

7.2 用 Qdrant(有 Web 界面可看)

# 用 Docker 启动 Qdrantdockerrun-p6333:6333-p6334:6334\-v$(pwd)/qdrant_storage:/qdrant/storage\qdrant/qdrant

启动后访问http://localhost:6333/dashboard就能看到图形化界面。

# pip install qdrant-clientfromqdrant_clientimportQdrantClientfromqdrant_client.modelsimportVectorParams,Distance,PointStruct# 连接client=QdrantClient(host="localhost",port=6333)# 创建 Collectionclient.create_collection(collection_name="tech_docs",vectors_config=VectorParams(size=4,distance=Distance.COSINE)# 这里用 4 维方便演示,实际常用 768 或 1536 维)# 插入数据(这里手动给向量,实际中由 Embedding 模型生成)client.upsert(collection_name="tech_docs",points=[PointStruct(id=1,vector=[0.9,0.1,0.2,0.3],payload={"title":"MySQL索引详解","category":"database"}),PointStruct(id=2,vector=[0.85,0.15,0.25,0.28],payload={"title":"PostgreSQL索引对比","category":"database"}),PointStruct(id=3,vector=[0.1,0.9,0.1,0.8],payload={"title":"Docker容器化实践","category":"devops"}),PointStruct(id=4,vector=[0.12,0.88,0.15,0.75],payload={"title":"K8s集群部署指南","category":"devops"}),])# 搜索:找和 [0.9, 0.1, 0.2, 0.35] 最相似的 2 条results=client.search(collection_name="tech_docs",query_vector=[0.9,0.1,0.2,0.35],limit=2)forrinresults:print(f"ID:{r.id}, 标题:{r.payload['title']}, 相似度:{r.score:.4f}")# 输出:# ID: 1, 标题: MySQL索引详解, 相似度: 0.9998# ID: 2, 标题: PostgreSQL索引对比, 相似度: 0.9979

然后在 Qdrant Dashboard 中可以:

✅ 看到 collection 列表 ✅ 看到每条数据的 payload(元数据,可读) ✅ 看到向量维度和配置 ✅ 执行向量搜索并查看结果 ✅ 查看集群状态和性能指标

八、实际项目中的典型使用场景

8.1 RAG(检索增强生成)

这是当前最火的应用场景:

用户提问: "公司的年假政策是什么?" │ ↓ Embedding 模型把问题转成向量 │ ↓ 向量数据库搜索:找到最相关的内部文档片段 │ ↓ Top 3 结果: 1. "员工入职满一年享有5天年假..." (相似度 0.94) 2. "年假可以分次使用,但..." (相似度 0.89) 3. "未休年假按日工资300%补偿..." (相似度 0.85) │ ↓ 把这些文档片段 + 用户问题 一起发给大模型 │ ↓ 大模型生成回答:"根据公司政策,入职满一年享有5天年假..."

8.2 以图搜图

上传一张鞋子照片 → 转成图像向量 → 在向量数据库中搜索 → 找到最相似的商品

8.3 语义搜索

搜索: "如何处理高并发" ↓ 返回: 1. "Redis缓存雪崩的解决方案" (关键词完全不同,但语义相关) 2. "Nginx负载均衡配置指南" 3. "数据库连接池优化"

九、常见问题 FAQ

Q1: 向量数据库能替代 MySQL 吗?

不能。它们解决的是完全不同的问题:

  • MySQL:精确存储和查询结构化数据
  • 向量数据库:基于语义相似度检索非结构化数据

实际项目中通常两者配合使用:MySQL 存业务数据,向量数据库存 Embedding 向量。

Q2: 一条数据的向量能看懂吗?

不能。向量是一组高维浮点数,人眼无法理解每一维代表什么。它更像是数据的"数字指纹",只有通过数学计算(距离/相似度)才能比较。

Q3: 我的数据量很小(几千条),需要用向量数据库吗?

可以用FAISS(纯 Python 库,无需部署服务)或Chroma(轻量嵌入式),甚至直接在 Python 里用 NumPy 做暴力搜索都够用:

importnumpyasnp# 1000 条 768 维向量,暴力搜索毫秒级完成vectors=np.random.rand(1000,768).astype('float32')query=np.random.rand(1,768).astype('float32')distances=np.linalg.norm(vectors-query,axis=1)top_k=np.argsort(distances)[:10]# 找最近的 10 条

Q4: Embedding 模型和向量数据库是什么关系?

Embedding 模型:负责把数据"翻译"成向量(编码器) 向量数据库:负责存储和检索这些向量(仓库 + 搜索引擎) 关系就像: 翻译官(Embedding)把各种语言翻译成统一的数字语言 图书馆(向量数据库)按这些数字的相似度整理书架,方便你找书

十、总结

向量数据库的核心要点可以归纳为以下六点:

1. 存什么:高维浮点数向量 + 元数据(标签、分类等结构化信息) + 原始数据(文本、图片链接等)。其中向量是核心,元数据用于辅助过滤,原始数据用于最终返回给用户。

2. 怎么查:以相似度搜索为主,本质就是"给一个向量,找出库里和它最接近的 N 条记录",返回的结果会附带一个相似度分数。

3. 怎么快:依靠 ANN(近似最近邻)索引算法,主流的有 HNSW(多层跳表式检索)和 IVF(先聚类再搜索),用极小的精度损失换取搜索速度的数量级提升。

4. 能看吗:部分产品提供了 GUI 工具,例如 Milvus 的 Attu、Qdrant 内置的 Dashboard,可以在界面上浏览集合、查看元数据、执行搜索。但向量列本身是一长串浮点数,肉眼无法直接理解,能看懂的只有元数据字段和原始文本。

5. 和 MySQL 的关系:互补而非替代。MySQL 负责精确存储和查询结构化业务数据,向量数据库负责基于语义相似度的检索。实际项目中两者通常配合使用。

6. 最火的应用场景:RAG(检索增强生成)、语义搜索、以图搜图、推荐系统,以及大模型应用中的知识库问答。


向量数据库并不神秘,本质上就是一个专门为高维向量设计的"检索引擎"。理解了这一点,再去学具体的 API 和使用方式就会非常顺畅。