PostgreSQL 中的序列(Sequence)
PostgreSQL 中的序列(Sequence)
PostgreSQL 完全支持序列(Sequence)对象,它是一种特殊的数据库对象,用于生成唯一的数值序列。序列是许多数据库设计中不可或缺的部分,特别是在需要自动生成主键值的场景中。
一 序列的基本概念
1.1 什么是序列
- 序列是一个特殊的单行表,用于生成有序的数值序列
- 生成的数值保证唯一(但不一定连续)
- 独立于事务,即使事务回滚,序列值也不会回退
1.2 典型应用场景
- 自动递增的主键生成
- 订单编号、发票编号等业务编号生成
- 任何需要唯一数字标识的场景
二 序列的基本操作
2.1 创建序列
-- 基本语法
CREATE [ { TEMPORARY | TEMP } | UNLOGGED ] SEQUENCE [ IF NOT EXISTS ] name[ AS data_type ][ INCREMENT [ BY ] increment ][ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ][ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ][ OWNED BY { table_name.column_name | NONE } ]-- 示例:创建简单序列
CREATE SEQUENCE order_id_seq START WITH 1000 INCREMENT BY 1;
2.2 使用序列
-- 获取下一个值
SELECT nextval('order_id_seq');-- 获取当前值(不增加序列)
SELECT currval('order_id_seq');-- 设置当前值(小心使用)
SELECT setval('order_id_seq', 2000);
2.3 在表中使用序列
-- 方法1:作为默认值
CREATE TABLE orders (id bigint PRIMARY KEY DEFAULT nextval('order_id_seq'),order_date date NOT NULL
);-- 方法2:使用SERIAL类型(自动创建序列)
CREATE TABLE products (id SERIAL PRIMARY KEY, -- 自动创建序列products_id_seqname text NOT NULL
);
三 序列的高级特性
3.1 序列与事务
- 序列操作是非事务性的:
nextval()
调用即使事务回滚也不会撤销 - 但
setval()
在事务中可以被回滚
3.2 性能优化选项
-- 使用CACHE提高性能(默认1)
CREATE SEQUENCE fast_seq CACHE 100;
-- 表示每次从序列中预取100个值到内存
3.3 循环序列
CREATE SEQUENCE cyclic_seqMINVALUE 1MAXVALUE 10CYCLE; -- 达到最大值后重新从1开始
四 序列管理
4.1 查看序列信息
-- 查看所有序列
SELECT * FROM pg_sequences;-- 查看特定序列定义
SELECT * FROM information_schema.sequences
WHERE sequence_name = 'order_id_seq';-- 查看序列的DLL语句
SELECT pg_get_serial_sequence('orders', 'id'); -- 返回关联的序列名
4.2 修改序列
ALTER SEQUENCE order_id_seq INCREMENT BY 2MAXVALUE 10000RESTART WITH 500CACHE 5;
4.3 删除序列
DROP SEQUENCE [ IF EXISTS ] sequence_name [, ...] [ CASCADE | RESTRICT ];
五 序列与SERIAL类型的区别
特性 | 序列(SEQUENCE) | SERIAL类型 |
---|---|---|
创建方式 | 显式创建 | 隐式自动创建 |
控制粒度 | 完全可控 | 自动管理 |
多表共享 | 可以 | 不能 |
命名规则 | 自定义 | 表名_列名_seq |
修改灵活性 | 高 | 低 |
六 实际应用示例
6.1 多表共享序列
-- 创建共享序列
CREATE SEQUENCE document_id_seq;-- 多个表使用同一序列
CREATE TABLE invoices (id bigint PRIMARY KEY DEFAULT nextval('document_id_seq'),amount numeric(10,2)
);CREATE TABLE receipts (id bigint PRIMARY KEY DEFAULT nextval('document_id_seq'),payment_date date
);
6.2 复杂编号规则
-- 创建带前缀的订单编号
CREATE SEQUENCE order_num_seq START WITH 1000;CREATE TABLE orders (id SERIAL PRIMARY KEY,order_number text NOT NULL DEFAULT 'ORD-' || to_char(CURRENT_DATE, 'YYYYMMDD-') || lpad(nextval('order_num_seq')::text, 6, '0'),customer_id integer NOT NULL
);
七 注意事项
- 间隙问题:序列可能产生间隔(由于缓存、事务回滚等)
- 安全考虑:序列值可预测,不适用于安全敏感场景
- 分布式环境:在分布式系统中可能需要特殊处理(如Snowflake算法)
- 性能影响:高并发下序列可能成为瓶颈,考虑适当增加CACHE值
PostgreSQL的序列实现非常成熟且功能丰富,可以满足绝大多数自动编号需求。对于更复杂的分布式ID生成需求,可以考虑使用UUID或专门的分布式ID生成算法。
更详细的内容请查看官方文档:
https://www.postgresql.org/docs/16/sql-createsequence.html
谨记:心存敬畏,行有所止。