跳转至

Supabase 开源 Firebase 替代

一句话概述

Supabase 是一个基于 PostgreSQL 的开源后端平台,提供数据库、认证、存储、实时订阅、Edge Functions 等"全家桶"服务,被称为"开源 Firebase 替代品",GitHub 99K+ Star,超过 200 万开发者使用,免费层无 API 请求限制。

核心知识点表格

知识点说明
官网https://supabase.com
项目地址https://github.com/supabase/supabase
GitHub Stars99,200+
核心数据库PostgreSQL(业界使用率 55.6%)
核心功能数据库 + Auth + Storage + Realtime + Edge Functions
API 类型REST(自动生成)+ GraphQL + Realtime WebSocket
向量搜索内置 pgvector 扩展
许可证Apache 2.0
估值$50 亿(2025年10月)
免费层2 个项目,无 API 请求限制

安装与配置

方式一:使用 Supabase Cloud(最简单)

1. 访问 https://supabase.com 注册账号
2. 点击 "New Project" 创建项目
3. 设置项目名、数据库密码、选择区域
4. 等待约 2 分钟,项目就绪
5. 在 Settings → API 中获取:
   - Project URL(如 https://xxx.supabase.co)
   - anon key(公开密钥,用于客户端)
   - service_role key(服务密钥,用于后端)

安装 Python 客户端

pip install supabase  # 安装 Supabase Python SDK

安装 JavaScript 客户端

npm install @supabase/supabase-js  # 安装 JS SDK

方式二:本地 Docker 开发

# 安装 Supabase CLI
npm install -g supabase  # 全局安装 CLI

# 初始化项目
supabase init  # 在当前目录创建 supabase 配置

# 启动本地 Supabase(包含所有服务)
supabase start  # 启动 PostgreSQL + Auth + Storage + Realtime 等

# 启动后会显示所有服务的地址和密钥
# API URL: http://localhost:54321
# DB URL: postgresql://postgres:postgres@localhost:54322/postgres
# Studio URL: http://localhost:54323  (数据库管理界面)

基本使用

初始化客户端

from supabase import create_client  # 导入 Supabase 客户端

# 初始化
url = "https://xxx.supabase.co"       # 你的项目 URL
key = "eyJhbGciOiJIUzI1NiIsInR..."    # 你的 anon key

supabase = create_client(url, key)     # 创建客户端

数据库 CRUD 操作

# === 创建数据(INSERT) ===
result = supabase.table("papers").insert({
    "title": "宏基因组分析方法综述",
    "abstract": "本文综述了主要的宏基因组分析方法...",
    "year": 2024,
    "topic": "metagenomics"
}).execute()

print(result.data)  # 插入的数据

# === 查询数据(SELECT) ===
result = supabase.table("papers") \
    .select("*") \                   # 选择所有列
    .eq("topic", "metagenomics") \   # WHERE topic = 'metagenomics'
    .gte("year", 2024) \             # AND year >= 2024
    .order("year", desc=True) \      # ORDER BY year DESC
    .limit(10) \                     # LIMIT 10
    .execute()

for paper in result.data:
    print(f"{paper['title']} ({paper['year']})")

# === 更新数据(UPDATE) ===
result = supabase.table("papers") \
    .update({"year": 2025}) \        # SET year = 2025
    .eq("id", 1) \                   # WHERE id = 1
    .execute()

# === 删除数据(DELETE) ===
result = supabase.table("papers") \
    .delete() \                      # DELETE
    .eq("id", 1) \                   # WHERE id = 1
    .execute()

用户认证

# 邮箱密码注册
result = supabase.auth.sign_up({
    "email": "user@example.com",
    "password": "securepassword123"
})

# 登录
result = supabase.auth.sign_in_with_password({
    "email": "user@example.com",
    "password": "securepassword123"
})

user = result.user              # 用户信息
session = result.session        # 会话信息(含 JWT token)
print(f"用户ID: {user.id}")

# 登出
supabase.auth.sign_out()

# OAuth 登录(Google、GitHub 等 20+ 社交登录)
result = supabase.auth.sign_in_with_oauth({
    "provider": "github"         # 使用 GitHub 登录
})

文件存储

# 创建存储桶
supabase.storage.create_bucket("papers", {"public": False})  # 私有桶

# 上传文件
with open("paper.pdf", "rb") as f:
    supabase.storage.from_("papers").upload(
        "2024/my-paper.pdf",    # 存储路径
        f,                       # 文件内容
        {"content-type": "application/pdf"}
    )

# 获取文件 URL
url = supabase.storage.from_("papers").get_public_url("2024/my-paper.pdf")
print(url)

# 下载文件
data = supabase.storage.from_("papers").download("2024/my-paper.pdf")

高级用法

实时订阅(Realtime)

# 监听数据库变化(实时推送)
def handle_change(payload):
    """数据变化时的回调函数"""
    print(f"事件类型: {payload['eventType']}")   # INSERT/UPDATE/DELETE
    print(f"新数据: {payload['new']}")            # 变化后的数据
    print(f"旧数据: {payload['old']}")            # 变化前的数据

# 订阅 papers 表的所有变化
channel = supabase.channel("papers-changes")
channel.on_postgres_changes(
    event="*",                    # 监听所有事件
    schema="public",              # schema 名
    table="papers",               # 表名
    callback=handle_change        # 回调函数
).subscribe()

向量搜索(pgvector)

-- 在 Supabase SQL 编辑器中启用 pgvector
CREATE EXTENSION IF NOT EXISTS vector;

-- 创建带向量列的表
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT,
    embedding vector(384)
);

-- 创建搜索函数
CREATE OR REPLACE FUNCTION match_documents(
    query_embedding vector(384),    -- 查询向量
    match_threshold float,          -- 相似度阈值
    match_count int                 -- 返回数量
)
RETURNS TABLE (
    id int,
    content text,
    similarity float
)
LANGUAGE sql STABLE
AS $$
    SELECT
        documents.id,
        documents.content,
        1 - (documents.embedding <=> query_embedding) AS similarity
    FROM documents
    WHERE 1 - (documents.embedding <=> query_embedding) > match_threshold
    ORDER BY documents.embedding <=> query_embedding
    LIMIT match_count;
$$;
# 在 Python 中调用向量搜索
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-MiniLM-L6-v2")
query_embedding = model.encode("糖尿病肠道菌群").tolist()

# 调用 Supabase RPC 函数
result = supabase.rpc("match_documents", {
    "query_embedding": query_embedding,
    "match_threshold": 0.7,
    "match_count": 5
}).execute()

for doc in result.data:
    print(f"相似度: {doc['similarity']:.4f} - {doc['content']}")

Row Level Security(行级安全)

-- RLS 让不同用户只能看到自己的数据

-- 启用 RLS
ALTER TABLE papers ENABLE ROW LEVEL SECURITY;

-- 创建策略:用户只能读取自己的数据
CREATE POLICY "Users can read own papers"
ON papers FOR SELECT
USING (auth.uid() = user_id);         -- auth.uid() 返回当前登录用户的 ID

-- 创建策略:用户只能插入自己的数据
CREATE POLICY "Users can insert own papers"
ON papers FOR INSERT
WITH CHECK (auth.uid() = user_id);

Edge Functions(Serverless 函数)

# 创建 Edge Function
supabase functions new hello-world  # 创建函数模板

# 编辑函数代码(TypeScript/Deno)
# supabase/functions/hello-world/index.ts
// supabase/functions/hello-world/index.ts
Deno.serve(async (req) => {
  const { name } = await req.json()   // 解析请求体
  const data = {
    message: `Hello ${name}!`,        // 返回消息
  }
  return new Response(
    JSON.stringify(data),             // 返回 JSON
    { headers: { "Content-Type": "application/json" } },
  )
})
# 部署函数
supabase functions deploy hello-world  # 部署到 Supabase

# 调用函数
curl -X POST https://xxx.supabase.co/functions/v1/hello-world \
  -H "Authorization: Bearer <anon-key>" \
  -d '{"name": "World"}'

常见报错与解决

报错信息原因解决方法
Invalid API keyAPI Key 错误检查 anon key 是否正确
RLS policy violation行级安全策略拒绝检查 RLS 策略是否允许当前操作
JWT expired登录 token 过期重新登录或刷新 token
Relation does not exist表不存在先在 SQL 编辑器或 Dashboard 创建表
Storage bucket not found存储桶不存在先创建存储桶
Function invocation failedEdge Function 报错查看函数日志排查

速查表

# === Supabase Python SDK 速查 ===
from supabase import create_client
sb = create_client(url, key)

# 数据库
sb.table("t").select("*").execute()                  # 查询所有
sb.table("t").select("*").eq("col", "val").execute()  # 条件查询
sb.table("t").insert({"col": "val"}).execute()        # 插入
sb.table("t").update({"col": "val"}).eq("id", 1).execute()  # 更新
sb.table("t").delete().eq("id", 1).execute()          # 删除

# 认证
sb.auth.sign_up({"email": "...", "password": "..."})
sb.auth.sign_in_with_password({"email": "...", "password": "..."})
sb.auth.sign_out()
sb.auth.get_user()

# 存储
sb.storage.from_("bucket").upload("path", file)
sb.storage.from_("bucket").download("path")
sb.storage.from_("bucket").get_public_url("path")

# RPC(调用数据库函数)
sb.rpc("function_name", {"param": "value"}).execute()

与同类工具对比

特性SupabaseFirebaseAppwritePocketBase
数据库PostgreSQLFirestore(NoSQL)MariaDBSQLite
开源Apache 2.0BSD-3MIT
自托管支持不支持支持支持
向量搜索pgvector不支持不支持不支持
SQL 支持完整 SQLNoSQL有限SQLite SQL
实时WebSocket原生WebSocketWebSocket
免费层2项目/无请求限制慷慨(有每日限制)自托管免费完全免费
社区99K+ Star最大46K+ Star43K+ Star

选择建议:如果你要做正式的 Web/App 后端项目,Supabase 是性价比最高的选择——PostgreSQL 的强大 + 开源无锁定。如果只是做个人小项目/原型,PocketBase 更轻量。