ParadeDB 把全文检索、向量搜索和混合搜索直接塞进 Postgres,不用再额外维护 Elasticsearch 或 Milvus。现在它在 Render 上正式可用,一键就能跑起来——对已经在用 Render 的团队来说,搜索基础设施的运维成本可以砍掉一大块。
ParadeDB 到底做了什么
ParadeDB 基于 Postgres 扩展 pg_search 和 pg_vector,在同一个数据库里同时提供:
- 全文检索:基于 Tantivy(Rust 写的高性能搜索引擎内核),支持 BM25 排序、分词器配置、字段权重调整。
- 向量搜索:基于
pgvector,支持 HNSW 索引和多种距离度量(cosine、L2、inner product)。 - 混合搜索:把全文和向量结果做融合排序,兼顾关键词精确匹配和语义相似度。
这意味着你不需要在应用层做"先查 ES 再查 Milvus 再合并"的编排逻辑——一条 SQL 就能搞定。
在 Render 上部署
Render 提供了一键部署按钮,但如果你想在现有项目里集成,用 Blueprint(Render 的 YAML 配置文件)更可控。下面是一个最小可用的 render.yaml:
services:
- type: pserv
name: paradedb
plan: starter # Render Postgres starter plan,按需升级
env: docker
dockerfilePath: ./Dockerfile
dockerContext: .
envVars:
- key: POSTGRES_USER
value: paradedb
- key: POSTGRES_PASSWORD
sync: false # Render 会自动生成安全密码
- key: POSTGRES_DB
value: searchdb
对应的 Dockerfile——直接拉 ParadeDB 官方镜像:
FROM paradedb/paradedb:latest
# ParadeDB 镜像已内置 pg_search 和 pgvector 扩展
# 无需额外安装,启动后 CREATE EXTENSION 即可使用
推送这个仓库到 GitHub,Render 会自动识别 render.yaml 并创建服务。如果你更倾向手动操作,也可以在 Render Dashboard 里选择 Deploy one-click 链接,30 秒内实例就能就绪。
实战:建索引、跑搜索
部署完成后,连上 Postgres,先启用扩展并建一张带搜索索引的表:
-- 启用 ParadeDB 的搜索扩展和向量扩展
CREATE EXTENSION pg_search;
CREATE EXTENSION vector;
-- 建一张产品表,同时存文本和向量
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
embedding VECTOR(1536) -- OpenAI text-embedding-ada-002 维度
);
-- 用 ParadeDB 的 BM25 索引做全文检索
-- idxname 是索引名,后面查询时要用
CALL paradedb.create_bm25(
index_name => 'products_search',
table_name => 'products',
key_field => 'id',
text_fields => '{"name": {"tokenizer": {"type": "default"}, "stemmer": "English"}, "description": {"tokenizer": {"type": "default"}, "stemmer": "English"}}'
);
-- 给向量列建 HNSW 索引
CREATE INDEX ON products USING hnsw (embedding vector_cosine_ops);
插入几条测试数据:
INSERT INTO products (name, description, embedding)
VALUES
('Mechanical Keyboard', 'Hot-swappable switches, RGB backlight, aluminum frame', '[0.12, 0.45, ...]'::vector), -- 实际向量需替换
('Wireless Mouse', 'Ergonomic design, 2.4GHz receiver, 18-month battery life', '[0.08, 0.33, ...]'::vector);
全文检索
-- 搜索名字或描述里含 "keyboard" 的产品,BM25 排序
SELECT * FROM paradedb.search(
index_name => 'products_search',
query => paradedb.parse('keyboard'),
limit => 10
);
向量搜索
-- 给一个查询向量,找最相似的 5 条产品
SELECT id, name, embedding <=> '[0.11, 0.44, ...]'::vector AS distance
FROM products
ORDER BY embedding <=> '[0.11, 0.44, ...]'::vector
LIMIT 5;
混合搜索
ParadeDB 支持把全文和向量结果做融合。一个典型做法是用子查询分别取结果再加权合并:
-- 全文结果
WITH bm25_hits AS (
SELECT id, paradedb.score(id) AS bm25_score
FROM paradedb.search(
index_name => 'products_search',
query => paradedb.parse('keyboard'),
limit => 20
)
),
-- 向量结果
vec_hits AS (
SELECT id, 1 - (embedding <=> '[0.11, 0.44, ...]'::vector) AS vec_score
FROM products
ORDER BY embedding <=> '[0.11, 0.44, ...]'::vector
LIMIT 20
)
-- 简单加权融合:0.7 * BM25 + 0.3 * 向量相似度
SELECT
COALESCE(b.id, v.id) AS id,
COALESCE(0.7 * b.bm25_score, 0) + COALESCE(0.3 * v.vec_score, 0) AS hybrid_score
FROM bm25_hits b
FULL OUTER JOIN vec_hits v ON b.id = v.id
ORDER BY hybrid_score DESC
LIMIT 10;
权重比例(0.7/0.3)按业务调整——关键词精确匹配重要的场景多给 BM25,语义召回重要的场景多给向量。
用 Python 调 ParadeDB
如果你的后端是 Python,连 ParadeDB 和连普通 Postgres 没区别,只是 SQL 更丰富:
import psycopg2
conn = psycopg2.connect(
host="your-paradedb.onrender.com",
port=5432,
dbname="searchdb",
user="paradedb",
password="RENDER_GENERATED_PASSWORD"
)
cur = conn.cursor()
# 全文检索
cur.execute("""
SELECT * FROM paradedb.search(
index_name => 'products_search',
query => paradedb.parse(%s),
limit => 10
)
""", ("keyboard",))
for row in cur.fetchall():
print(row)
cur.close()
conn.close()
把 host 和 password 换成 Render 控制台里显示的内部连接串即可。Render 的 Postgres 服务默认提供内部和外部两个 URL——应用部署在 Render 上时用内部 URL,本地调试用外部 URL。
上线前的几件事
| 检查项 | 说明 |
|---|---|
| 扩展是否已启用 | pg_search 和 vector 两个扩展都要 CREATE EXTENSION,ParadeDB 镜像已预装但不会自动启用 |
| 索引策略 | BM25 索引建在查询高频字段上;向量索引的 m 和 ef_construction 参数按数据量调,默认值对小数据集够用 |
| Render Plan 选择 | Starter plan 适合验证;生产环境看数据量和并发选 Standard 或 Pro,向量索引对内存敏感 |
| 连接池 | Render Postgres 连接数有限制,高并发场景用 PgBouncer 或应用层连接池 |
| 备份 | Render Postgres 自动做每日备份,但向量索引重建成本高,确认备份频率满足需求 |
ParadeDB 在 Render 上的定位很清晰:你已经在用 Postgres、已经在用 Render,又需要搜索能力——那就别再另起一套 Elasticsearch 集群了。一键部署,SQL 里直接查,运维复杂度从"两个系统"降到"一个数据库"。