【Milvus】稀疏向量 和 稠密向量

【Milvus】稀疏向量 和 稠密向量

1. 基础定义

(1)稀疏向量

向量​绝大多数维度都有非 0 浮点值,几乎不存在大量零元素,存储为完整定长数组。

  • 存储格式:完整数组,所有维度都占用内存;
  • 典型来源:LLM/BERT/Sentence-BERT 输出语义 Embedding、图像特征;
  • 示例(768 维文本稠密向量简化示意):
    [0.12, 0.56, 0.33, 0.89, 0.27, ...] 几乎无 0。

(2)稠密向量

向量​95% 以上维度都是 0,仅少量维度存在有效值,只存储「(维度下标,权重值)」,舍弃全部零值节省空间。

  • 存储格式:键值对,只记录非零位置;
  • 典型来源:TF-IDF、Splade、词袋、分词关键词权重;
  • 示例(完整 10000 维,仅 2 个有效值):
    完整展开:[0,0,0,2.1,0,...,1.6,0,0]​稀疏存储简写:{(3, 2.1), (892, 1.6)}

2. 核心差异对比

(1)存储占用

  • 稠密:维度越高内存线性暴涨,768 维单条向量约 3KB;
  • 稀疏:总维度再大也不占空间,只看非零词数量,万维、十万维向量体积很小。

(2)相似度计算逻辑

  • 稠密:余弦 / 内积 / L2 距离,遍历全部维度做运算;
  • 稀疏:仅计算两个向量共同存在的非零维度,零值直接跳过,关键词匹配速度更快。

(3)向量数据库索引适配

向量类型 支持索引 不支持索引
稠密向量 HNSW、IVF_FLAT、IVF_PQ 稀疏倒排索引
稀疏向量 SPARSE_INVERTED_INDEX(稀疏倒排) HNSW

注意:Milvus 中稠密、稀疏向量必须分开字段、分开建索引,不能混用一套索引。

(4)检索能力侧重

  • 稠密向量:​语义模糊匹配,擅长同义、转述、上下文理解;
    例:“汽车” 和 “小轿车” 能匹配到;

  • 稀疏向量:​字面关键词精准匹配,擅长专有名词、实体、专业术语不漏召回;

    例:只有包含 “汽车” 这个分词才会命中,不会泛化语义。

3. 业务使用场景

(1)稠密向量适用场景

  • RAG 语义检索、多模态图文匹配;
  • 句子、段落、长文本语义相似度;
  • 模糊语义搜索、同义内容召回。

(2)稀疏向量适用场景

  • 关键词精准检索、知识库专有名词匹配;
  • 短文本标题、标签、商品类目过滤;
  • 解决稠密向量丢失实体关键词的问题。
  • 稠密向量(dense_vec):召回语义相近的文档;
  • 稀疏向量(sparse_vec):召回包含核心关键词、专业术语的文档;
  • 两路分数加权融合排序,兼顾语义理解和​关键词精准度,大幅提升召回准确率。

4. 优缺点:

(1)稠密向量

  • 优点:语义表达能力强,模糊匹配效果好,HNSW 检索成熟稳定;

  • 缺点:高维内存开销大,纯关键词召回容易漏实体。

(2)稀疏向量

  • 优点:超大维度极低存储,关键词检索速度极快;
  • 缺点:无泛化语义能力,只能字面匹配,无法使用 HNSW 索引。

5. 向量类型汇总

向量类型 精度 / 存储 类型 入门 / 进阶 特点 使用前提
FLOAT_VECTOR fp32,4 字节 / 维度 稠密向量 基础通用 精度最高、通用首选 无转换,Embedding 直接输出,所有 RAG 首选
BFLOAT16_VECTOR bf16 半精度,2 字节 / 维度 稠密向量 进阶压缩 节省空间,小数精度表现好 向量需转为 bf16 格式,适配大模型 GPU 推理
FLOAT16_VECTOR fp16 半精度,2 字节 / 维度 稠密向量 进阶压缩 数值范围大,小数精度弱 尾数精度更高,适合图像特征向量
INT8_VECTOR int8 整型,1 字节 / 维度 稠密向量 进阶极致压缩 存储 -128~127 整数向量 原始 fp32 向量必须做量化映射,海量数据降内存专用
BINARY_VECTOR 1 比特 / 维度 稠密向量 特殊稠密 稀疏向量,适配超高维度场景 图像哈希二值特征,维度必须是 8 的倍数
SPARSE_FLOAT_VECTOR 按需存储 稀疏向量 基础通用 二进制向量,极致压缩存储 稀疏向量,适配超高维度场景

6. 创建 稠密向量 和 稀疏向量

(1)SQL创建

-- 创建 FLOAT_VECTOR
create collection vec_demo_fp32 (
    id bigint primary key autoincrement,
    text varchar(2000),
    vec_fp32 FLOAT VECTOR(768)
);

-- 创建 BFLOAT16_VECTOR
create collection vec_demo_bf16 (
    id bigint primary key autoincrement,
    text varchar(2000),
    vec_bf16 BFLOAT16_VECTOR(768)
);

-- 创建 FLOAT16_VECTOR
create collection vec_demo_fp16 (
    id bigint primary key autoincrement,
    text varchar(2000),
    vec_fp16 FLOAT16_VECTOR(768)
);

-- 创建 INT8_VECTOR
create collection vec_demo_int8 (
    id bigint primary key autoincrement,
    text varchar(2000),
    vec_int8 INT8_VECTOR(768)
);

-- 创建 BINARY_VECTOR
create collection vec_demo_bin (
    id bigint primary key autoincrement,
    text varchar(2000),
    vec_bin BINARY_VECTOR(512)
);

-- 创建 SPARSE_FLOAT_VECTOR
create collection vec_demo_sparse (
    id bigint primary key autoincrement,
    text varchar(2000),
    sparse_vec SPARSE_FLOAT_VECTOR
);

(2)Python SDK Schema

from pymilvus import FieldSchema, DataType

# 创建 FLOAT_VECTOR
field_fp32 = FieldSchema(
    name="vec_fp32",
    dtype=DataType.FLOAT_VECTOR,
    dim=768
)

# 创建 BFLOAT16_VECTOR
field_bf16 = FieldSchema(
    name="vec_bf16",
    dtype=DataType.BFLOAT16_VECTOR,
    dim=768
)

# 创建 FLOAT16_VECTOR
field_fp16 = FieldSchema(
    name="vec_fp16",
    dtype=DataType.FLOAT16_VECTOR,
    dim=768
)

# 创建 INT8_VECTOR
field_int8 = FieldSchema(
    name="vec_int8",
    dtype=DataType.INT8_VECTOR,
    dim=768
)

# 创建 BINARY_VECTOR
field_bin = FieldSchema(
    name="vec_bin",
    dtype=DataType.BINARY_VECTOR,
    dim=512
)

# 创建 SPARSE_FLOAT_VECTOR
field_sparse = FieldSchema(
    name="sparse_vec",
    dtype=DataType.SPARSE_FLOAT_VECTOR
)

# 组装完整通用基础字段
base_fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=2000)
]

posted @ 2026-07-20 20:25  静心笃行。  阅读(25)  评论(0)    收藏  举报