天天看点

震精 - PostgreSQL 单机3.9 万亿/天(计数器、序列、自增)

postgresql , 计数器 , 序列 , 自增值

数据库中,自增序列是常见的需求,例如计数,主键,唯一值,或者自动生成的流水号等等。

因此序列这个功能就应运而生,序列的功能在很多商业数据库中都支持需求,postgresql当然也支持,而且更好用。

在postgresql中可以创建多个序列,设置序列的起始值,步长,缓存大小,是否轮回等。

序列的应用场景

1. 作为字段默认值,default nextval('序列名');

2. 作为继承表的分布键

例如某个表有64个继承表,为了区分每个继承表的数据,可以将继承表的主键都按64取模,得到的结果不同来区分,使用步长很好的解决这个问题。

3. 作为计数器

4. 其他

那么postgresql序列的性能怎样呢?

<a href="http://thebuild.com/blog/2015/10/30/dont-assume-postgresql-is-slow/">http://thebuild.com/blog/2015/10/30/dont-assume-postgresql-is-slow/</a>

这个是某位网友的测试,我接下来会在某个32核的机器上测试一下,序列值的生成性能将达到每秒4.5千万。

使用unix socket连接,厕所12种场景,每次取多条时,统一为每次取10万条。

1. 单个序列(nocache),1个客户端,每个客户端,每次取一条

瓶颈

2. 单个序列(nocache),1个客户端,每个客户端,每次取多条

3. 单个序列(cache),1个客户端,每个客户端,每次取一条

4. 单个序列(cache),1个客户端,每个客户端,每次取多条

5. 单个序列(nocache),64个客户端,每个客户端,每次取一条

6. 多个序列(nocache),64个客户端,每个客户端,每次取一条

7. 单个序列(nocache),64个客户端,每个客户端,每次取多条

8. 多个序列(nocache),64个客户端,每个客户端,每次取多条

9. 单个序列(cache),64个客户端,每个客户端,每次取一条

10. 多个序列(cache),64个客户端,每个客户端,每次取一条

11. 单个序列(cache),64个客户端,每个客户端,每次取多条

12. 多个序列(cache),64个客户端,每个客户端,每次取多条

如果需要较为正确的perf诊断,pg的编译参数要改一下。

<a href="https://github.com/digoal/blog/blob/master/201611/20161129_01.md">《postgresql 源码性能诊断(perf profiling)指南》</a>

1. 序列的cache是会话层级的,例如一次cache 100个序列值,那么一次会消耗100,如果会话退出,这100个没有被用完的序列值也会被消耗掉。

cache的好处是减少锁冲突。

如果你不能用cache,那么可以用多个序列来解决锁冲突的问题。

如果需要并轨,只需要将多个序列的步长设为一样,同时起始值错开即可并轨。

2. 单个序列值,并发批量取序列值,如何提升性能?

设置cache

3. 并发单步取序列值,不允许cache的情况下,如何提升性能?

使用多个序列,每个会话对应一个序列,多个序列要求步长一致,起始值不一致即可。

4. 从上面的测试情况来看,理论上多个序列的性能应该更好,但是测试使用了<code>||</code>来拼接出序列名,带来了额外的开销,所以性能并未体现有些。

以单序列,批量并行取序列值的最好成绩来估算,每秒生成4550万自增值,那么一天可以生成3.9万亿个自增值,你想让它成为瓶颈都难。