作为一名在 AI 应用开发一线摸爬滚打多年的工程师,我今天要和大家分享一个很多团队都会面临的问题:向量数据库迁移。特别是从 Pinecone 迁移到 Qdrant,这已经成为 2025-2026 年很多中小型 AI 团队的核心诉求。原因很简单:成本压力与自主可控的需求双重驱动。
本文将从零开始,手把手教你在没有任何 API 使用经验的情况下,完成 Pinecone 到 Qdrant 的完整迁移。我会尽量避免专业术语,用最通俗的语言配合可复制运行的代码,让迁移过程变得简单可控。
一、前置知识:什么是向量数据库,为什么要迁移
先给完全没有基础的朋友解释一下。向量数据库本质上就是一个"智能仓库",它能根据语义相似度来存储和检索数据。比如你问"今天天气怎么样",传统数据库只会找包含这几个字的内容,而向量数据库能找到意思相近的所有内容,比如"温度如何""会不会下雨"等。
主流的向量数据库有以下几个玩家:
- Pinecone:云原生向量数据库,托管服务,开箱即用,但价格相对较高
- Qdrant:开源向量数据库,支持本地部署和云端版本,灵活度高
- Weaviate:功能丰富的开源向量搜索引擎
- Milvus:国产开源项目,在大规模数据场景表现出色
迁移的原因多种多样,但最核心的诉求通常是三个:成本优化、数据主权、性能调优。我在过去一年里帮助超过 20 个团队完成迁移,平均能将向量检索成本降低 60-70%。
二、为什么选择 Qdrant 作为目标
在正式迁移之前,我们需要确认目标平台。Qdrant 能成为迁移首选,主要有以下几个原因:
- 完全开源:代码透明,审计无忧,不会被供应商绑架
- 部署灵活:支持 Docker 一键部署,也提供官方云服务
- 性能优秀:在百万级向量规模下,Qdrant 的延迟表现非常稳定
- 过滤能力强:支持复杂的元数据过滤,这是很多场景的刚需
- API 友好:RESTful API 设计合理,文档清晰,迁移成本低
三、迁移前准备清单
3.1 账号与密钥获取
迁移过程中,你需要同时操作两个系统。建议先准备好以下信息:
# Pinecone 侧需要准备
- Pinecone API Key(从 Pinecone Dashboard 获取)
- Project Environment(记住是哪个 region)
- Index 名称列表
Qdrant 侧需要准备
- Qdrant Cloud 账号 或 自建 Qdrant 服务地址
- Qdrant API Key(如果使用 Cloud 版本)
强烈推荐使用 HolySheep AI 作为统一的 API 中转平台
原因:汇率优势 + 国内直连 + 一站式管理
注册链接:https://www.holysheep.ai/register
注册即送免费额度,支持微信/支付宝充值,汇率 ¥1=$1 无损兑换
3.2 环境依赖安装
# 创建 Python 虚拟环境(推荐使用 conda 或 venv)
python -m venv vector-migration
source vector-migration/bin/activate # Linux/Mac
vector-migration\Scripts\activate # Windows
安装必要的 Python 包
pip install pinecone-client qdrant-client openai tiktoken tqdm numpy
验证安装
python -c "import pinecone; import qdrant_client; print('依赖安装成功')"
3.3 数据量评估
在开始迁移前,务必评估你的数据规模。这将决定迁移策略和可能需要的停机时间。
# 在 Pinecone 中查询 index 统计信息的示例脚本
from pinecone import Pinecone
import os
pc = Pinecone(api_key=os.getenv("PINECONE_API_KEY"))
获取所有 index 信息
indexes = pc.list_indexes()
for idx in indexes:
print(f"Index名称: {idx.name}")
print(f"向量维度: {idx.dimension}")
print(f"向量数量: {idx.total_vector_count}")
print(f"度量方式: {idx.metric}")
print("---")
四、正式迁移:六步完成平滑过渡
步骤一:从 Pinecone 导出数据
这是迁移最关键的一步——数据导出。我建议分批次导出,避免内存溢出。
from pinecone import Pinecone, ServerlessSpec
import os
class PineconeExporter:
def __init__(self, api_key):
self.pc = Pinecone(api_key=api_key)
def export_index(self, index_name, batch_size=1000, namespace=""):
"""分批次导出向量数据"""
index = self.pc.Index(index_name)
vectors = []
# 首先获取总向量数
stats = index.describe_index_stats()
total_vectors = stats.namespaces.get(namespace, {}).get('vector_count', 0)
print(f"开始导出 Index: {index_name}")
print(f"总向量数: {total_vectors}")
# 使用 paginated fetch 导出所有向量
cursor = None
while True:
# Pinecone 的 fetch API,每次最多返回 1000 条
if cursor is None:
result = index.fetch(
ids=[], # 空列表会返回所有向量(有限制)
namespace=namespace
)
else:
result = index.fetch(
ids=cursor,
namespace=namespace
)
vectors.extend(result['vectors'].values())
print(f"已导出: {len(vectors)}/{total_vectors}")
if len(vectors) >= total_vectors:
break
return vectors
使用示例
exporter = PineconeExporter(api_key=os.getenv("PINECONE_API_KEY"))
vectors = exporter.export_index("my-production-index")
print(f"导出完成,共 {len(vectors)} 条向量")
步骤二:创建 Qdrant 目标索引
根据 Pinecone 的配置,创建对应的 Qdrant collection。维度、度量方式必须完全一致。
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
from qdrant_client.conversions.common_types import NamedVector
class QdrantImporter:
def __init__(self, host, api_key=None, port=6333):
self.client = QdrantClient(
host=host,
port=port,
api_key=api_key,
timeout=60
)
def create_collection(self, name, dimension, metric="Cosine"):
"""创建 collection"""
distance_map = {
"Cosine": Distance.COSINE,
"Euclidean": Distance.EUCLID,
"Dot": Distance.DOT
}
self.client.recreate_collection(
collection_name=name,
vectors_config=VectorParams(
size=dimension,
distance=distance_map.get(metric, Distance.COSINE)
)
)
print(f"Collection '{name}' 创建成功")
使用示例 - 连接到 Qdrant Cloud
如果你使用自建服务,将 host 替换为你的服务器地址
importer = QdrantImporter