Skip to main content

Postgres 数据类型

typealiasdesc
bigintint8有符号的八字节整数
bigserialserial8自增的八字节整数
bit[(n)]固定长度的位串
bit varying[(n)]varbit[(n)]可变长度的位串
booleanbool逻辑布尔值(真/假)
box平面上的矩形框
bytea二进制数据(“字节数组”)
character[(n)]char[(n)]固定长度的字符串
character varying[(n)]varchar[(n)]可变长度的字符串
cidrIPv4或IPv6网络地址
circle平面上的圆
date日历日期(年,月,日)
double precisionfloat8双精度浮点数(8字节)
inetIPv4或IPv6主机地址
integerint, int4有符号的四字节整数
interval [ fields ][(p)]时间跨度
json文本JSON数据
jsonb二进制JSON数据,解构后的
line平面上的无限线
lseg平面上的线段
macaddrMAC(媒体访问控制)地址
macaddr8MAC(媒体访问控制)地址(EUI-64格式)
money货币金额
numeric[(p,s)]decimal[(p,s)]可选择精度的精确数字
path平面上的几何路径
pg_lsnPostgreSQL日志序列号
pg_snapshot用户级事务ID快照
point平面上的几何点
polygon平面上的封闭几何路径
realfloat4单精度浮点数(4字节)
smallintint2有符号的两字节整数
smallserialserial2自增的两字节整数
serialserial4自增的四字节整数
text可变长度的字符串
time[(p)] [without time zone]时间(无时区)
time[(p)] with time zonetimetz包含时区的时间
timestamp[(p)] [without time zone]日期和时间(无时区)
timestamp[(p)] with time zonetimestamptz包含时区的日期和时间
tsquery文本搜索查询
tsvector文本搜索文档
txid_snapshot用户级事务ID快照(已弃用;见 pg_snapshot)
uuid通用唯一标识符
xmlXML数据
-- array length
SELECT array_length(ARRAY[1,2,3], 1);
-- remove element from array
SELECT array_remove(ARRAY[1,2,3], 2);
SELECT array_remove(ARRAY ['A','B','C'], 'B');

-- end of month
select to_char(date_trunc('month', '2021-02-27'::date) + interval '1 month - 1 day', 'YYYY-MM-DD');

UUID

  • 原生支持 uuid 类型 - 底层为 byte[4] - 比存字符串效率更高
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- pg 13 后不需要扩展也能使用该函数
SELECT gen_random_uuid();

OID

时间日期

NameMinMaxResolutionSize
timestamp4713 BC294276 AD微秒8 bytes
timestamptz4713 BC294276 AD微秒8 bytes
date4713 BC5874897 AD4 bytes
time00:00:0024:00:00微秒8 bytes
timetz00:00:00+145924:00:00-1459微秒12 bytes
interval-178000000 years178000000 years微秒16 bytes
  • interval
    • interval '1 month - 1 day' 等价 interval '1 month' - interval '1 day'
-- 时区缩写
select * from pg_timezone_abbrevs;
-- 时区名字
select * from pg_timezone_names;

-- unix timestamp -> timestamp
select to_timestamp(1633072800);
/*
* 表示拆分后的 interval(时间间隔)的数据结构。
*
* 出于历史原因,该结构体的设计参考了用于时间戳的 struct pg_tm。
* 与时间戳不同,interval 的月和年字段没有特殊含义:仅为零或非零。
* 注意各字段可能为负数;但由于从 struct Interval 转换时的除法运算,
* 只有 tm_mday 可能为 INT_MIN。这一点很重要,因为某些代码路径下
* 可能需要对这些值取相反数。
*/
struct pg_itm
{
int tm_usec; // 微秒
int tm_sec; // 秒
int tm_min; // 分钟
int64 tm_hour; // 小时(需要较宽的数据类型)
int tm_mday; // 天
int tm_mon; // 月
int tm_year; // 年
};

typedef int64 Timestamp;
typedef int64 TimestampTz;
typedef int64 TimeOffset;

/*
* interval 类型的存储结构体。
*
* time 字段存储除天、月、年以外的所有时间单位(如秒、微秒等)。
* day 字段存储天数,放在 time 字段之后以保证内存对齐。
* month 字段存储月和年,同样放在 time 字段之后以保证对齐。
*/
typedef struct
{
TimeOffset time; /* 除天、月、年以外的所有时间单位 */
int32 day; /* 天数,紧跟在 time 后面以保证对齐 */
int32 month; /* 月和年,紧跟在 time 后面以保证对齐 */
} Interval;

二进制数据

  • BinaryFilesInDB
  • 使用 bytea 或 text,都使用 toast
  • 单记录最大 1G
  • 每个表最多 40 亿 > 2KB 的记录
  • 在读写时可能需要编码解码
  • 对内存要求较高,即便数据量较少

金额类型

经纬度

ARRAY

CREATE TABLE test (
id serial PRIMARY KEY,
tags text[]
);

-- filter array[]
SELECT * FROM test WHERE 'tag' = ANY(tags);
SELECT * FROM test WHERE tags @> ARRAY['tag1', 'tag2'];
-- array to string
SELECT array_to_string('{1,2}'::text[], ',', '');

select array[1,2,3];

FAQ

VARCHAR vs TEXT

INT vs BIGINT

  • 在 64 位的服务器上, 两者占用的空间相同
  • 因此建议使用 bigint