PostgreSQL 字符类型
下面给你一份 PostgreSQL 字符类型(Character Types)最完整、最清晰、最实用的总结,包含:
- PostgreSQL 字符类型有哪些
- 适用场景
- 优缺点
- 性能与存储对比
- 最佳实践总结(重点)
内容简明但专业,适合实际后端开发使用(FastAPI + PostgreSQL)。
PostgreSQL 提供主要 5 类字符相关类型:
| 类型 | 描述 |
|---|---|
| char(n) | 固定长度字符串 |
| varchar(n) | 可变长度,有长度限制 |
| varchar / text | 可变长度,无长度限制 |
| text | 超大文本 |
| citext | 不区分大小写的 text/varchar(扩展) |
另外还有:
| 类型 | 描述 |
|---|---|
| bytea | 二进制数据 |
| json / jsonb | JSON 文本类型 |
下面我们逐个讲解。
✅ 场景
- 格式固定的值,例如:
- 性别:char(1) -> ‘M’/‘F’
- 状态码:char(1)、char(2)
- ISO 国家代码:char(2)
- 固定格式编码
👍 优点
- 长度固定的存储,某些场景中节省空间
- 对齐优化(极少见,几乎用不到)
👎 缺点
- PostgreSQL 会 自动补空格到固定长度
- 查询时会被 trim 掉,但视觉上容易误导
- 写入不合格的长度会报错
- 维护麻烦
❗ 结论
除非字段本来就是固定长度,否则不要使用 char(n)。
✅ 场景
- 用户名 varchar(50)
- 标题 title varchar(200)
- 手机号(11 字符)varchar(20)
- 标签 label varchar(100)
👍 优点
- 有长度限制,保证输入安全
- 常用于输入字段
- 对性能影响非常小,是常用类型
👎 缺点
- 设计不当时:乱用过小长度导致未来需要迁移
- 大多数场景并不真的需要长度限制
❗ 结论
- 用于有 “业务约束长度” 的字段。
- 例如:手机号码 email 用户名等。
※ 在 PostgreSQL 中,varchar 和 text 完全等价,性能也一样。 这一点和 MySQL 完全不同。
✅ 场景
- 文章标题:title text(长标题)
- 内容主体:content text
- URL / JSON 字符串
- 不确定是否有长度上限的字段
👍 优点
- 无长度限制,灵活
- PostgreSQL 内部优化良好,无额外性能损耗
- 与 varchar(n) 一样可建立索引
- 是 PostgreSQL 中最常用字符类型
👎 缺点
- 无“硬限制”可能导致业务字段输入过长(可通过 check constraint 解决)
❗ 结论
默认应该使用 text。
出于简单、灵活、易维护的原则,text 是最推荐的类型。
需要启用扩展:
CREATE EXTENSION IF NOT EXISTS citext;
✅ 场景
- 需要大小写不敏感的字段:
- username
- 标签名
👍 优点
- 自动大小写不敏感比较(无需 LOWER())
- 建索引时自动大小写不敏感
- 查询性能高于 lower(column)
👎 缺点
- 是扩展,不是内置
- 与某些框架兼容性略差(FastAPI + SQLAlchemy 没问题)
❗ 结论
email / username 最佳类型:citext(而不是 varchar)
✅ 场景
- 图片二进制
- 文件内容
- 加密数据
❗ 不推荐存储大文件,用对象存储替代(S3、OSS)。
文本类结构化数据:
- 用户设置
- 扩展字段(无 schema)
- 标签数组
- 元数据
推荐 jsonb(有索引、可查询)。
| 类型 | 查询性能 | 存储效率 | 使用复杂度 |
|---|---|---|---|
| char(n) | ❌ 慢 & 补空格 | 不一定省空间 | 高 |
| varchar(n) | ✅ 快 | ✅ 高 | 中 |
| varchar | ✅ 快 | ✅ 高 | 低 |
| text | ✅ 快 | ✅ 高 | 最低(最佳) |
| citext | ✅ 中高 | ✅ 高 | 中 |
Postgres 中 varchar = text 性能和存储无差别,不像 MySQL。
🔥 最推荐
| 场景 | 数据类型 |
|---|---|
| 长文本(文章、内容) | text |
| 字符串(无固定长度) | text |
| email / username | citext |
| 手机号、身份证、代码 | varchar(n) |
| 固定长度标识 | char(n)(极少用) |
| JSON 数据 | jsonb |
你问过类似问题:
title 和 content 长度未知,但是 title 要比 content 很多,用什么类型?
我的建议:
- title -> varchar(255) 或 text
- content -> text
理由:
- Postgres 中 varchar 和 text 一样快
- content 是长文本,绝对用 text