22人参与 • 2026-01-19 • MsSqlserver
本文将系统性地剖析 postgresql 中各类数据类型的特性、适用场景、潜在陷阱及最佳实践,覆盖数值、字符、时间、布尔、枚举、网络、json、几何、全文搜索、范围、自定义类型等核心类别,并结合真实案例说明选型逻辑。
在关系型数据库设计中,数据类型的选取看似基础,实则深刻影响着系统的存储效率、查询性能、数据完整性、扩展能力乃至长期维护成本。postgresql 作为功能最丰富的开源数据库之一,提供了远超传统 sql 标准的多样化数据类型——从精确的数值类型、灵活的时间处理,到强大的 jsonb、地理空间、全文搜索、自定义复合类型等。然而,“多”并不等于“易用”,错误的类型选择往往导致隐性性能瓶颈、存储浪费或逻辑错误。在深入具体类型前,需明确以下通用原则:
numeric),避免浮点误差。0.1 + 0.2 = 0.30000000000000004(浮点问题)。date 而非 text 存储日期;inet 而非 varchar 存储 ip 地址。int,但业务增长后需支持分布式 id(如 snowflake),应预留为 bigint。check 约束或域(domain)强化业务规则。
create domain email as text check (value ~ '^[^@]+@[^@]+\.[^@]+$');
终极心法: “用最精确、最紧凑、最语义化的类型表达你的数据。”
数据库不仅是存储引擎,更是业务逻辑的载体。正确的类型选择,是构建健壮、高效、可维护系统的第一步。
postgresql 提供多种数值类型,核心区别在于精度、范围、存储大小及是否为精确计算。
| 类型 | 范围 | 存储 | 适用场景 |
|---|---|---|---|
smallint | -32768 ~ +32767 | 2 字节 | 枚举状态码、小计数器 |
integer | -2147483648 ~ +2147483647 | 4 字节 | 主键、外键、常规计数(默认选择) |
bigint | ±9223372036854775807 | 8 字节 | 大流量 id(如订单号)、分布式系统 |
选型建议:
integer;若预计超 20 亿行,直接用 bigint。smallint 仅比 integer 节省 2 字节,但溢出风险高,现代系统内存充足,通常不值得冒险。| 类型 | 精度 | 存储 | 特性 |
|---|---|---|---|
real | 6 位十进制 | 4 字节 | ieee 754 单精度 |
double precision | 15 位十进制 | 8 字节 | ieee 754 双精度 |
适用场景:
numeric(precision, scale),如 numeric(10,2) 表示共 10 位,小数占 2 位。典型应用:
numeric(19,4)(支持万亿级金额,4 位小数用于汇率计算)numeric(5,2)(如 99.99%)⚠️ 注意:
numeric无默认精度,若省略(p,s),则可存储任意精度值(但性能更差)。
postgresql 对字符类型的处理与其他数据库有显著差异。
| 类型 | 含义 | 存储 | 性能 | 建议 |
|---|---|---|---|---|
text | 无长度限制 | 可变 | 最优 | 首选 |
varchar(n) | 最大 n 字符 | 可变 | 略低于 text | 需强制长度限制时 |
char(n) | 固定 n 字符,不足补空格 | 固定 | 最差 | 避免使用 |
关键事实:
text、varchar、char 底层存储完全相同(均使用 varlena 结构)。varchar(n) 的长度检查会带来轻微 cpu 开销。char(n) 会自动填充空格,导致比较时需 trim(),极易引发逻辑错误。结论:
text;varchar(18) 并配合 check 约束;char(n)。text 可存储至 1gb(受 toast 机制支持)。-- 创建大对象 select lo_create(0); -- 返回 oid
时间处理是数据库常见痛点,postgresql 提供了清晰的类型划分。
| 类型 | 含义 | 时区 | 存储 | 推荐 |
|---|---|---|---|---|
date | 日期(年月日) | 无 | 4 字节 | 日历事件 |
time | 时间(时分秒) | 无 | 8 字节 | 营业时间 |
timestamp | 日期+时间 | 无 | 8 字节 | 避免使用 |
timestamptz | 日期+时间+时区 | 有 | 8 字节 | 绝对首选 |
关键区别:
timestamp:不带时区,存储字面值。例如 '2025-01-01 12:00:00' 在任何时区都显示相同。timestamptz:带时区,存储为 utc,显示时自动转换为客户端时区。示例:
set timezone = 'asia/shanghai';
insert into logs(ts) values ('2025-01-01 12:00:00'); -- 存为 utc 04:00
set timezone = 'utc';
select ts from logs; -- 显示 2025-01-01 04:00:00+00最佳实践:
timestamptz;where 中对时间字段使用函数(破坏索引),改用范围查询:-- 好
where created_at >= '2025-01-01' and created_at < '2025-02-01'
-- 坏
where date_trunc('month', created_at) = '2025-01-01''1 day 2 hours'。select now() + interval '30 days'; -- 30 天后
true、false、nullint(0/1)或 char(‘y’/‘n’)表示布尔状态。select * from users where is_active;
create type order_status as enum ('pending', 'shipped', 'delivered', 'cancelled');
create table orders (id serial, status order_status);
varchar 节省空间alter type ... add value(postgresql 10+ 支持)替代方案:若需频繁变更或国际化,可用参照表(lookup table)代替。
postgresql 原生支持网络数据类型,避免字符串存储的弊端。
| 类型 | 示例 | 用途 |
|---|---|---|
inet | '192.168.1.1', '2001:db8::1' | ip 地址(含子网掩码) |
cidr | '192.168.1.0/24' | 网络地址块 |
macaddr | '08:00:2b:01:02:03' | mac 地址 |
优势:
select '192.168.1.10'::inet << '192.168.1.0/24'; -- true(属于该网段)
应用场景:访问日志、防火墙规则、设备管理。
详见前文《jsonb 详解》,此处强调选型要点:
jsonb vs json:除非需保留原始格式(如审计),否则一律用 jsonb。示例:
-- 好:用户偏好设置 create table users (id serial, name text, prefs jsonb); -- 坏:将订单明细存为 json -- 应拆分为 orders + order_items 两张表
point、line、lseg、box、path、polygon、circlecreate table locations (name text, coord point); select name from locations where coord <@ box '((0,0),(10,10))';
postgis 扩展后,提供 geometry、geography 类型create extension postgis; create table places (name text, geom geometry(point, 4326));
postgresql 内置全文检索能力,无需外部搜索引擎。
tsvector:文档的词位向量(已分词、去停用词、标准化)tsquery:搜索条件表达式工作流程:
-- 创建向量
update articles set tsv = to_tsvector('english', title || ' ' || body);
-- 创建 gin 索引
create index idx_tsv on articles using gin(tsv);
-- 搜索
select * from articles where tsv @@ to_tsquery('english', 'database & performance');优势:
postgresql 独创的范围类型,优雅解决“时间段”、“价格区间”等问题。
| 类型 | 示例 |
|---|---|
int4range | [10,20) |
numrange | (1.5, 5.5] |
tsrange | ['2025-01-01', '2025-12-31') |
tstzrange | 带时区的时间范围 |
select int4range(10, 20) && int4range(15, 25); -- true
create table room_bookings (
room text,
during tsrange,
exclude using gist (room with =, during with &&)
);
应用场景:日历预约、价格策略、资源调度。
create type address as (street text, city text, zip text); create table users (id serial, home address);
select (home).city from users;
适用场景:逻辑上紧密关联的属性组(如地址、坐标)。
create domain us_postal_code as text check (value ~ '^\d{5}$');
create table addresses (zip us_postal_code);
优势:复用约束逻辑,提升代码可读性。
numeric、date 等专用类型。bigserial;null = null 返回 null(非 true),导致逻辑错误。is null / is not null 判断;0、'')。最后总结:数据类型选型决策树
数值:
numericbigint(防溢出)double precision(仅限科学计算)字符:
textvarchar(n)char(n)时间:
timestamptzdatetstzrange状态/分类:
enum半结构化:
jsonbtsvector特殊领域:
inetpostgisrange到此这篇关于postgresql选择合适的数据类型的文章就介绍到这了,更多相关postgresql数据类型内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论