PostgreSQL 中 sequence 的用法

PostgreSQL 中 sequence 的用法

介绍

sequence 是 pg 自带的高效的自增id工具(也叫序列)。sequence 使用了轻量级锁的方式来做到高效自增id的,所以会比 UPDATE 行锁快。sequence 的返回数据类型默认是64位的整数,pg 10 可以自定 smallint, integer 或者是 bigint。

用法

使用 sequence

# 创建
CREATE SEQUENCE temp_seq;

# 获取下一个sequence
select nextval('temp_seq'); # 1

# 设置 sequence 的开始值
select setval('temp_seq', 42);

# 获取下一个sequence
select nextval('temp_seq'); # 43

# 创建一个自动循环的 sequence
CREATE SEQUENCE temp_seq2 MINVALUE 18 MAXVALUE 20 CYCLE;

select nextval('temp_seq2'); # 18
select nextval('temp_seq2'); # 19
select nextval('temp_seq2'); # 20
select nextval('temp_seq2'); # 18

# 创建表的时候把类型设置为 serial 会自动创建一个 sequence

CREATE TABLE temp_seq_table (id serial);

postgres=# \d temp_seq_table
                         Table "public.temp_seq_table"
 Column |  Type   |                          Modifiers
--------+---------+-------------------------------------------------------------
 id     | integer | not null default nextval('temp_seq_table_id_seq'::regclass)
 
# 自动创建了 sequence temp_seq_table_id_seq 

CACHE 参数

sequence 是可以保证自增数据不重复的,也就是说每次自增后都会持久化保存,那么为了继续提高性能,可以加上 CACHE 参数(默认为1),每个进程(连接)可以缓存一个子序列在当前进程内存里面,当子序列用完了才会去原序列取新的子序列。

这个用个例子简单说一下,创建 sequence temp_seq3 时用了 CACHE 10,A session 可以获取到的值是 1...10,B session 可以获取到的值是 11...20,那么获取顺序可能是 (A, A, B, A),返回值是 (1, 2, 11, 3),这个不是严格自增的序列,但可以保证回次返回都是唯一的,用了 CYCLE 参数的除外。

根据文档和源码( link 第80行),缓存在内存里面的最大值(cached)是每个进程都不一样的,所以如果要求严格自增的服务不能用 CACHE。

CREATE SEQUENCE temp_seq3 CACHE 10;
select nextval('temp_seq3'); # 1
select nextval('temp_seq3'); # 2
# \q 退出 psql 重新链接
select nextval('temp_seq3'); # 11

pgbench 压测

这里写三种用 pg 做自增id的方式

  1. 直接用 UPDATE SET RETURNING
  2. 用默认值的 SEQUENCE
  3. 用 CACHE=10 的SEQUENCE

测试命令,在 MacOS 上用 docker 开一个 pg 在里面运行一下 pgbench 脚本,其中 sql.sql 的内容替换成对应的压测脚本。

pgbench -c 10 -T 10 -f sql.sql -U postgres postgres
# 准备数据库表
CREATE TABLE temp_incr_table (id integer primary key, val integer);
INSERT INTO temp_incr_table VALUES(1, 1);

# 上面例子创建的 temp_seq 和 temp_seq3 都会用于压测

UPDATE;

BEGIN;
    UPDATE temp_incr_table SET val = val + 1 WHERE id = 1 RETURNING val;
END;

TPS: 986

CACHE 默认为1 的sequence

BEGIN;
    SELECT nextval('temp_seq');
END;

TPS: 7332

CACHE 默认为10 的sequence

BEGIN;
    SELECT nextval('temp_seq3');
END;

TPS: 7451

压测总结

  1. sequence 比 update 快 8 倍左右,在并发量大的时候更明显,而且从 pg 运行原理来说也是可以证明的,mvvc 里面的 update 都会写一份新的数据,有额外的写和额外的vacuum工作,而且行锁还需要把锁的上下文记录到stat表。
  2. CACHE 优化不明显,理论上是可以减少更新 buffer 的次数,后续可以在生产环境的机器上验证一下。

ref

看看微信的分布式id生成器,原理都差不多,"实际应用中每次提升的步长为10000" = "CACHE 10000"。link

以上优化已经是用在友好速搭电商系统的订单号和优惠券号生成服务中,为商家提供更快更可靠的服务。

友好速搭是国内领先的电商服务和云技术提供方。依托技术、营销、企业服务三大业务,为高端零售品牌打造个性化交易系统,并快速链接行业资源与精准流量,使品牌价值最大化。官网链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容