数据STUDIO

向量数据库已死?PostgreSQL 这个新功能,让闭源尬住了

Image

Image
一实习生用47分钟在现有Postgres里实现了向量搜索 ---- 完全免费

整个向量数据库市场都在集体屏息。

泡沫刚刚破灭。

还记得去年所有人都在说你需要专门的向量数据库吗?当 Pinecone 融资1.38亿美元、Weaviate 成为独角兽时?当每个创业公司的融资PPT第三页都写着“由[某向量数据库]驱动”时?

PostgreSQL 刚刚发布了 pgvector 0.8.0,其新功能让专用向量数据库看起来像是昂贵的过度设计。对于价值数十亿美元的向量数据库行业来说,这个时机再糟糕不过了。

这是真实发生的故事。

场景重现:我们是如何走到今天的?

当 ChatGPT 在2022年底爆发时,企业突然发现他们需要地方来存储嵌入向量,以实现检索增强生成。一夜之间,存储和搜索数百万个高维向量成为了必备能力。

专用向量数据库的推销话术很简单:你的传统数据库处理不了这个。你需要专门的基础设施。你需要我们。

仅在2023年4月,Pinecone 和 Chroma 就完成了巨额融资轮。信息很明确:向量数据库是未来,如果你想构建AI应用,最好跟上潮流。

但有个问题。

大多数公司已经有一个数据库了。一个非常好的数据库。PostgreSQL 几十年来一直是Web应用的主力,每天为从 Instagram 到 Spotify 的公司处理数十亿事务。

于是开发者们问了那个显而易见的问题:我们能在Postgres里直接做向量搜索吗?

向量数据库厂商说不行。他们写博客文章解释为什么你需要专门的基础设施。他们把 HNSW 算法和近似最近邻搜索说得像火箭科学一样复杂。

然后 pgvector 出现了,并且说:实际上,你可以。

真正的变革:pgvector 0.8.0 带来了什么

这次更新增加了迭代索引扫描和智能查询规划。这些不是花哨的功能,而是那种彻底改变游戏规则的、看似枯燥的基础设施改进。

让我用程序员能理解的方式解释这些功能到底做了什么:

1. 迭代索引扫描:告别“零结果”尴尬

以前,当你通过元数据过滤向量时(比如“显示价格低于50美元的类似产品”),如果过滤器太严格,你可能会得到零个结果。现在,pgvector 可以增量扫描,直到找到足够匹配项。

# 以前:过滤太严格可能导致没有结果
# 现在:自动找到最接近的匹配项
query = """
SELECT product_name, price, 
       embedding <=> %s as similarity
FROM products
WHERE price < 50 AND category = 'electronics'
ORDER BY similarity
LIMIT 10;
"""

2. 智能查询规划:Postgres现在更“聪明”了

PostgreSQL 现在知道何时使用你的常规索引而不是向量索引。有时,在过滤条件上使用 B-tree 索引比扫描向量更快。Postgres 会自动判断选择最优策略。

# Postgres会自动选择最佳查询计划:
# 1. 先用价格索引过滤
# 2. 再在结果集中进行向量搜索
# 全部自动完成,无需手动优化

实战演示:用pgvector构建产品推荐系统

让我用一个完整的例子展示如何在现有产品表中添加向量搜索。

步骤1:启用扩展并修改表结构

# 首先启用pgvector扩展
import psycopg2

conn = psycopg2.connect(
    host="localhost",
    database="your_db",
    user="your_user",
    password="your_password"
)
cur = conn.cursor()

# 启用pgvector扩展
cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")

# 为现有产品表添加向量列
cur.execute("""
    ALTER TABLE products 
    ADD COLUMN IF NOT EXISTS embedding vector(1536);
"""
)
conn.commit()

步骤2:创建混合索引

# 创建向量索引(支持余弦相似度)
cur.execute("""
    CREATE INDEX IF NOT EXISTS idx_product_embedding 
    ON products USING hnsw (embedding vector_cosine_ops);
"""
)

# 常规索引仍然有效
cur.execute("""
    CREATE INDEX IF NOT EXISTS idx_product_price 
    ON products(price);
"""
)

# 复合索引也很容易创建
cur.execute("""
    CREATE INDEX IF NOT EXISTS idx_product_category_price 
    ON products(category, price);
"""
)
conn.commit()

步骤3:执行智能查询

deffind_similar_products(product_id, max_price=None, category_filter=None):
"""
    查找类似产品,支持价格和类别过滤
    """

# 1. 获取目标产品的向量
    cur.execute("""
        SELECT embedding FROM products WHERE id = %s;
    """
, (product_id,))
    target_embedding = cur.fetchone()[0]

# 2. 构建动态查询
    query = """
        SELECT id, name, price, category,
               (embedding <=> %s) as similarity
        FROM products
        WHERE id != %s
    """

    params = [target_embedding, product_id]

# 动态添加过滤器
if max_price:
        query += " AND price <= %s"
        params.append(max_price)

if category_filter:
        query += " AND category = %s"
        params.append(category_filter)

    query += " ORDER BY similarity LIMIT 10;"

# 3. 执行查询(Postgres会自动选择最优执行计划)
    cur.execute(query, params)
return cur.fetchall()

# 使用示例:查找类似但更便宜的电子产品
similar = find_similar_products(
    product_id=123,
    max_price=50,
    category_filter='electronics'
)

成本对比:数字不会说谎

让我们算一笔实实在在的经济账。

专用向量数据库方案(以 Pinecone 为例)

  • 费用:每月每百万向量约70美元
  • 基础设施:需要单独部署和管理
  • 数据同步:主数据库和向量存储之间的同步复杂性
  • 学习成本:需要学习新的查询语言和API

PostgreSQL + pgvector 方案

  • 扩展费用:完全免费
  • 基础设施:你已经为Postgres付费了
  • 数据同步:零同步,因为所有数据都在一处
  • 学习成本:你的团队已经熟悉SQL
# 假设你有100万产品向量
pinecone_cost = 70# 美元/月

# 使用pgvector的成本计算
pgvector_cost = 0# 扩展本身免费
# 额外存储成本(可以忽略不计)
additional_storage = 1000000 * 1536 * 4 / (1024**3)  # 约5.7GB
storage_cost = 5.7 * 0.1# 约0.57美元/月(按云存储价格估算)

print(f"专用方案月成本: ${pinecone_cost}")
print(f"pgvector方案月成本: ${storage_cost:.2f}")
print(f"每月节省: ${pinecone_cost - storage_cost:.2f}")
print(f"每年节省: ${(pinecone_cost - storage_cost) * 12:.2f}")

架构对比:简单 vs 复杂

传统方案:双数据库架构

用户查询
    ↓
应用服务器
    ↓
    ├──> PostgreSQL(结构化数据:用户、订单、产品)
    └──> Pinecone(向量数据:产品嵌入)
    ↓
数据同步服务(复杂度高,延迟问题)
    ↓
最终一致性问题(数据不同步的风险)

pgvector方案:一体化架构

用户查询
    ↓
应用服务器
    ↓
PostgreSQL(所有数据:结构化+向量)
    ↓
原子操作、强一致性、简化运维

性能真相:差距正在迅速缩小

向量数据库公司喜欢谈论基准测试。但他们没告诉你的是:

  1. pgvector 0.7.0 已经支持:

  • 半精度向量(存储减半)
  • 支持高达4000维的索引
  • 二值量化支持高达64000维
  • 真正的瓶颈往往不是搜索速度:

    • 应用服务器和向量数据库之间的网络延迟
    • Postgres 和向量存储之间的数据同步延迟
    • 不理解过滤条件的查询规划
    # 性能对比测试框架
    import time

    defbenchmark_search(conn, query_func, iterations=100):
    """基准测试函数"""
        times = []
    for i in range(iterations):
            start = time.time()
            query_func()
            times.append(time.time() - start)

    return {
    'avg': sum(times) / len(times),
    'p95': sorted(times)[int(len(times) * 0.95)],
    'p99': sorted(times)[int(len(times) * 0.99)]
        }

    # 对于大多数应用(百万级向量),pgvector性能完全足够
    # 而且避免了网络往返开销

    何时你确实需要专用向量数据库?

    我不是说向量数据库已经死了。确实存在需要它们的合理场景:

    1. 超大规模向量:如果你有数十亿个嵌入向量
    2. 纯向量工作负载:如果90%的查询都是纯向量相似度搜索,几乎没有过滤
    3. 需要完全托管的基础设施:如果你无法自己运维Postgres

    但关键是:大多数公司不符合这些情况。大多数公司有:

    • 数百万(不是数十亿)向量
    • 复杂的过滤需求(价格、类别、时间范围等)
    • 现有的PostgreSQL基础设施

    对他们来说,pgvector 不是妥协,而是更好的选择。

    如何迁移到 pgvector?

    如果你已经在使用专用向量数据库,迁移路径很清晰:

    defmigrate_from_pinecone_to_pgvector():
    """
        从Pinecone迁移到pgvector的步骤
        """

    # 1. 导出Pinecone中的所有向量
        pinecone_vectors = export_from_pinecone()

    # 2. 在Postgres中创建对应表
        setup_pgvector_tables()

    # 3. 批量导入数据
        batch_size = 1000
    for i in range(0, len(pinecone_vectors), batch_size):
            batch = pinecone_vectors[i:i+batch_size]
            import_to_pgvector(batch)

    # 4. 创建索引
        create_vector_indexes()

    # 5. 双写运行一段时间,验证结果一致性
        run_parallel_and_compare()

    # 6. 切换流量,停用Pinecone
        switch_traffic_and_decommission()

    行业影响:技术选型的本质

    市场已经不再单纯关注“向量数据库”这个概念,因为说实话,谁真的关心数据库类型呢?重要的是:你能否快速构建AI应用,并且不用烧钱就能维护它?

    向量数据库厂商看到了这个趋势。Weaviate 现在称自己为“AI原生数据库”,Pinecone 变成了“知识平台”。他们正在向上游移动,添加向量存储之外的功能。

    这可能是明智之举。因为在“做一个好数据库”这件事上跟Postgres竞争,是一场必输的战斗。

    Postgres有:

    • 30年的持续开发
    • 数百万用户
    • 一个向量数据库无法匹敌的生态系统

    最佳实践指南

    如果你决定使用 pgvector,以下是最佳实践:

    # 1. 选择合适的距离度量
    # 根据你的使用场景选择:
    # - vector_cosine_ops: 余弦相似度(推荐)
    # - vector_l2_ops: 欧几里得距离
    # - vector_ip_ops: 内积

    # 2. 优化索引参数
    cur.execute("""
        CREATE INDEX idx_optimized 
        ON products USING hnsw (embedding vector_cosine_ops)
        WITH (m = 16, ef_construction = 64);
    """
    )

    # 3. 定期维护索引
    cur.execute("VACUUM ANALYZE products;")

    # 4. 监控性能
    cur.execute("""
        SELECT * FROM pg_stat_user_indexes 
        WHERE indexrelname LIKE '%vector%';
    """
    )

    # 5. 备份策略(和普通Postgres表一样)
    # pg_dump 完全支持向量列

    写在最后

    向量数据库的炒作周期已经结束。不是因为向量数据库不好,而是因为对于大多数用例来说,它们没有必要。

    PostgreSQL + pgvector 让你能够利用已有的事务、备份和安全功能,同时添加向量能力。这种组合很难被击败。

    在你签署下一个 Pinecone 合同之前,问自己三个问题:

    1. 我们真的需要另一个数据库吗?
    2. 我们的数据规模真的超出了pgvector的能力范围吗?
    3. 我们是在解决实际问题,还是仅仅在追赶潮流?

    因为很可能,你已经拥有了所需的一切。它一直在你的基础设施中,安静地为你的应用程序提供动力,而其他人却在追逐新的热门技术。

    Postgres 刚刚提醒我们:为什么“枯燥”的技术最终会获胜。

    你在实际项目中是怎么做向量搜索的?是否也遇到过专用方案过度设计的问题?欢迎在评论区分享你的经验和看法~

    🏴‍☠️宝藏级🏴‍☠️ 原创公众号『数据STUDIO』内容超级硬核。公众号以Python为核心语言,垂直于数据科学领域,包括可戳👉Python|MySQL|数据分析|数据可视化|机器学习与数据挖掘|爬虫等,从入门到进阶!

    长按👇关注- 数据STUDIO -设为星标,干货速递ImageImage