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万亿个自增值,你想让它成为瓶颈都难。