关系型数据库选型
要点
- PostgreSQL、MySQL、SQLite 是 Hono 项目最常用的三种关系型数据库
- PostgreSQL 功能最全面,JSON 支持好,扩展丰富,是 AI 项目的首选
- MySQL 生态成熟,云服务商支持好,团队熟悉度高
- SQLite 轻量零配置,适合开发、测试和小项目,Cloudflare D1 基于 SQLite
- Edge 环境(Workers、Deno Deploy)通常只能用远程连接或 SQLite
- 选型时团队熟悉度往往比技术差异更重要
1. 三大数据库概览
| 维度 | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
| 定位 | 功能全面的企业级数据库 | 生态成熟的 Web 数据库 | 嵌入式轻量数据库 |
| JSON 支持 | JSONB,索引和查询能力强 | JSON 类型,功能较弱 | JSON1 扩展,基础支持 |
| 向量支持 | pgvector 扩展 | 无原生支持 | sqlite-vss 扩展 |
| 并发模型 | 多版本并发控制(MVCC) | 锁机制 | 单写者 |
| 事务 | 完整 ACID,支持多种隔离级别 | 完整 ACID | 完整 ACID |
| 扩展性 | 扩展丰富(PostGIS、pgvector 等) | 插件较少 | 扩展有限 |
| 部署 | 需要独立服务 | 需要独立服务 | 嵌入式,无服务 |
| 云托管 | 各大云均有 | 各大云均有 | 无(除 D1) |
2. PostgreSQL
PostgreSQL 是 AI 项目的首选关系型数据库,原因:
- JSONB 类型:可以在关系型表里存储 JSON,支持 GIN 索引,查询性能接近专用文档数据库
- pgvector 扩展:同一数据库存储业务数据和向量数据,减少运维复杂度
- 扩展生态:PostGIS(地理信息)、TimescaleDB(时序数据)等扩展覆盖各种场景
- 标准兼容:严格遵循 SQL 标准,迁移到其他数据库时语法差异小
2.1 与 Hono 集成
// src/lib/db.ts
import { Pool } from 'pg'
import { drizzle } from 'drizzle-orm/node-postgres'
import * as schema from './schema'
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
})
export const db = drizzle(pool, { schema })// src/schema.ts
import { pgTable, uuid, text, timestamp, jsonb } from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
email: text('email').notNull().unique(),
name: text('name').notNull(),
metadata: jsonb('metadata'), // JSONB 类型
createdAt: timestamp('created_at').defaultNow(),
})2.2 pgvector 集成
// src/schema.ts
import { pgTable, uuid, text, vector } from 'drizzle-orm/pg-core'
export const documentEmbeddings = pgTable('document_embeddings', {
id: uuid('id').primaryKey().defaultRandom(),
documentId: uuid('document_id').notNull(),
chunk: text('chunk').notNull(),
embedding: vector('embedding', { dimensions: 1536 }).notNull(),
createdAt: timestamp('created_at').defaultNow(),
})// 相似度查询
import { sql } from 'drizzle-orm'
import { db } from './lib/db'
import { documentEmbeddings } from './schema'
const queryEmbedding = [0.1, 0.2, ...] // 1536 维
const results = await db
.select({
id: documentEmbeddings.id,
chunk: documentEmbeddings.chunk,
similarity: sql`1 - (${documentEmbeddings.embedding} <=> ${queryEmbedding})`,
})
.from(documentEmbeddings)
.orderBy(sql`${documentEmbeddings.embedding} <=> ${queryEmbedding}`)
.limit(5)2.3 适用场景
- 需要 JSONB 存储半结构化数据
- 需要向量检索(pgvector)
- 需要地理信息(PostGIS)
- 团队有一定 PostgreSQL 经验
- 项目可能扩展到复杂查询场景
3. MySQL
MySQL 是国内使用最广泛的关系型数据库,优势:
- 生态成熟:云服务商、ORM、工具链支持完善
- 团队熟悉:国内开发者普遍熟悉 MySQL
- 云托管丰富:阿里云 RDS、腾讯云 CDB、AWS RDS 等
- 性能稳定:读性能优秀,适合读多写少的场景
3.1 与 Hono 集成
// src/lib/db.ts
import { createPool } from 'mysql2/promise'
import { drizzle } from 'drizzle-orm/mysql2'
import * as schema from './schema'
const pool = await createPool({
uri: process.env.DATABASE_URL,
})
export const db = drizzle(pool, { schema })// src/schema.ts
import { mysqlTable, varchar, json, timestamp } from 'drizzle-orm/mysql-core'
export const users = mysqlTable('users', {
id: varchar('id', { length: 36 }).primaryKey(),
email: varchar('email', { length: 255 }).notNull().unique(),
name: varchar('name', { length: 255 }).notNull(),
metadata: json('metadata'), // JSON 类型
createdAt: timestamp('created_at').defaultNow(),
})3.2 与 PostgreSQL 的差异
- JSON 支持:MySQL 的 JSON 类型功能较弱,不支持索引(5.7+ 支持生成列索引)
- 向量支持:无原生向量扩展,需要外部向量数据库
- 语法差异:自增主键、字符串函数、日期函数等有差异
- 事务隔离:默认隔离级别不同(MySQL 默认 REPEATABLE READ,PostgreSQL 默认 READ COMMITTED)
3.3 适用场景
- 团队熟悉 MySQL
- 云服务商提供优质的 MySQL 托管服务
- 不需要复杂的 JSON 查询或向量检索
- 读多写少的场景
4. SQLite
SQLite 是嵌入式数据库,数据存在单个文件里,不需要独立的服务进程。
优势:
- 零配置:不需要安装、启动数据库服务
- 轻量:单个文件,便于备份和迁移
- 性能:读性能优秀,适合读多写少
- Edge 兼容:Cloudflare D1 基于 SQLite,适合 Workers 环境
限制:
- 单写者:同一时刻只能有一个写操作,不适合高并发写入
- 无网络访问:本地文件,不能跨机器共享
- 扩展有限:功能不如 PostgreSQL 和 MySQL 丰富
4.1 本地开发
SQLite 是本地开发的最佳选择——不需要启动数据库服务,数据存在文件里,重启不丢失:
// src/lib/db.ts
import Database from 'better-sqlite3'
import { drizzle } from 'drizzle-orm/better-sqlite3'
import * as schema from './schema'
const sqlite = new Database('local.db')
export const db = drizzle(sqlite, { schema })4.2 Cloudflare D1
D1 是 Cloudflare Workers 的托管 SQLite 服务:
// src/lib/db.ts
import { drizzle } from 'drizzle-orm/d1'
import * as schema from './schema'
export interface Env {
DB: D1Database
}
export default {
async fetch(request: Request, env: Env) {
const db = drizzle(env.DB, { schema })
// 使用 db 查询
},
}D1 的限制:
- 数据库大小限制 10GB(免费)或 100GB(付费)
- 每天写入次数有限(免费 5M 行,付费 50M 行)
- 不支持某些 SQLite 扩展
4.3 适用场景
- 本地开发和测试
- 小项目、原型验证
- Cloudflare Workers 环境
- 读多写少的场景
- 数据量小(单表少于百万行)
5. 选型决策树
是否需要 Edge 环境(Workers、Deno Deploy)?
├── 是 → 数据量小?
│ ├── 是 → SQLite / D1
│ └── 否 → 远程连接 PostgreSQL / MySQL
└── 否 → 是否需要 JSON 查询或向量检索?
├── 是 → PostgreSQL(pgvector)
└── 否 → 团队熟悉度?
├── PostgreSQL → PostgreSQL
├── MySQL → MySQL
└── 都不熟悉 → PostgreSQL(功能更全面)
6. 环境差异化配置
实际项目里,不同环境可能使用不同的数据库:
// src/lib/db.ts
import { Pool } from 'pg'
import Database from 'better-sqlite3'
import { drizzle } from 'drizzle-orm/node-postgres'
import { drizzle as drizzleSqlite } from 'drizzle-orm/better-sqlite3'
const env = process.env.NODE_ENV
if (env === 'production' || env === 'staging') {
// 生产环境用 PostgreSQL
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
export const db = drizzle(pool, { schema })
} else {
// 开发/测试环境用 SQLite
const sqlite = new Database('local.db')
export const db = drizzleSqlite(sqlite, { schema })
}Drizzle 支持多种数据库后端,schema 定义可以复用:
// src/schema.ts
// 这个 schema 可以同时用于 PostgreSQL 和 SQLite
import { pgTable, uuid, text } from 'drizzle-orm/pg-core'
// 或
import { sqliteTable, text } from 'drizzle-orm/sqlite-core'
// 但通常建议按数据库类型分开定义7. 迁移考量
如果项目后期需要迁移数据库(例如从 SQLite 迁移到 PostgreSQL),需要注意:
- 数据类型差异:SQLite 的 TEXT vs PostgreSQL 的 VARCHAR、UUID 等
- 自增主键:SQLite 的
INTEGER PRIMARY KEYvs PostgreSQL 的SERIAL或UUID - 日期时间:SQLite 存字符串,PostgreSQL 有 TIMESTAMP 类型
- JSON:SQLite 的 JSON1 vs PostgreSQL 的 JSONB
- 迁移工具:Drizzle Kit 支持生成不同数据库的迁移脚本
迁移成本在可控范围内,前提是使用 ORM 而不是手写 SQL。
8. 性能基准
简单的性能对比(仅供参考,实际性能取决于具体场景):
| 操作 | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
| 单行插入 | 快 | 快 | 快 |
| 批量插入 | 快 | 快 | 快 |
| 主键查询 | 快 | 快 | 快 |
| 范围查询 | 快 | 快 | 快 |
| 复杂 JOIN | 快 | 中等 | 慢 |
| 并发写入 | 好(MVCC) | 中等 | 差(单写者) |
| JSON 查询 | 快(JSONB) | 慢 | 慢 |
| 向量检索 | 快(pgvector) | 不支持 | 慢(sqlite-vss) |
SQLite 在并发写入场景下性能差,是因为同一时刻只能有一个写事务。如果项目有高并发写入需求,不要用 SQLite。
总结
关系型数据库选型是 AI 项目的基础决策。PostgreSQL、MySQL、SQLite 各有适用场景。
这一节涉及到的几个判断:
- PostgreSQL:功能最全面,JSON 支持好,pgvector 支持向量检索,是 AI 项目的首选
- MySQL:生态成熟,团队熟悉度高,适合不需要复杂 JSON 查询或向量检索的项目
- SQLite:零配置、轻量,适合开发测试、小项目、Edge 环境
- Edge 环境:Cloudflare Workers 用 D1(SQLite),其他 Edge 环境远程连接
- 环境差异化:生产用 PostgreSQL/MySQL,开发用 SQLite
- 迁移成本:使用 ORM 可以降低迁移成本
选型原则:
- 先考虑环境约束:Edge 环境只能用 SQLite 或远程连接
- 再考虑功能需求:需要 JSON 查询或向量检索,选 PostgreSQL
- 最后考虑团队熟悉度:功能差异不大时,团队熟悉哪个用哪个
下一篇看 PostgreSQL 实践——深入 PostgreSQL 的特性,以及与 Hono 项目的集成细节。