Greenplum数据增量导入的唯一值自增处理

简介: 阿里云的Greenplum(以下简称GP)已经公测了一段时间,陆续接到很多用户的反馈。其中一些使用上的问题比较有趣,在这里与大家分享一下。 其中一个case是字段的唯一键和自增值问题。在导入GP之前,某id字段已经保证了唯一性,但在此次导入之后,可能会有更多的导入,这个时候希望GP在原来最大id值

阿里云的Greenplum(以下简称GP)已经公测了一段时间,陆续接到很多用户的反馈。其中一些使用上的问题比较有趣,在这里与大家分享一下。

其中一个case是字段的唯一键和自增值问题。在导入GP之前,某id字段已经保证了唯一性,但在此次导入之后,可能会有更多的导入,这个时候希望GP在原来最大id值的基础上自增。

GP是在PostgreSQL(以下简称PG)上开发而来,其操作基本沿用。在PG上,实现自增的方法是通过serial:

postgres=> create table tuniq(id serial, name text);
CREATE TABLE
postgres=> insert into tuniq (name) values('zero');
INSERT 0 1
postgres=> insert into tuniq (name) values('second');
INSERT 0 1
postgres=> 
postgres=> 
postgres=> select * from tuniq;
 id |  name  
----+--------
  1 | zero
  2 | second
(2 rows)

这里的serial,并不是一个数据类型,而是通过建立一个全局序列“tuniq_id_seq”(表名_字段名_seq)实现的,每次插入的时候会从这个seq中取值作为字段的默认值,从而做到自增。

那么,如果你执行下面的语句会怎么样?

postgres=> insert into tuniq (id, name) values(1, 'second');

在id没有唯一约束的情况下,这是可以执行成功的。原因是id字段并没有加任何约束,而serial只是简单的从sequence给id赋值而已。这样就带来一个问题:

postgres=> select * from tuniq;
 id |  name  
----+--------
  1 | zero
  2 | second
  1 | second
(3 rows)

如果在这个字段上有唯一约束的话,那么开始的时候导入包括id在内的数据,之后执行不包括id的插入的时候,就会去从sequence取值。而这个时候,因为sequence的当前最新值尚未更新,所以可能会出现与已导入数据冲突的情况,如:

postgres=> create table tuniq(id serial unique, name text);
CREATE TABLE
postgres=> 
postgres=> 
postgres=> insert into tuniq values(0, 'zero');
INSERT 0 1
postgres=> insert into tuniq values(1, 'first');                                                                                                                                                           INSERT 0 1
postgres=> select * from tuniq;                                                                                                                                                                             id | name  
----+-------
  0 | zero
  1 | first
(2 rows)

postgres=> insert into tuniq (name) values('second');
ERROR:  duplicate key value violates unique constraint "tuniq_id_key"
DETAIL:  Key (id)=(1) already exists.

这个问题的解决方法也很简单:

postgres=> select setval('tuniq_id_seq', max(id)) from tuniq;
 setval 
--------
      1
(1 row)

postgres=> insert into tuniq (name) values('second');
INSERT 0 1
postgres=> select * from tuniq;
 id |  name  
----+--------
  0 | zero
  1 | first
  2 | second
(3 rows)

更详细的用法和解释参考这里

那如果是开始加了唯一键约束,但没有采用serial该如何做到字段值的继续递增?

正所谓:知其然,知其所以然。serial的原理,不过是从sequence取值作为字段的默认值而已。那如果想要做到类似的方式,用同样的方式做就好了。

让我们模拟一下这个场景:

postgres=> create table tuniq(id int unique, name text); 
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "tuniq_id_key" for table "tuniq"
CREATE TABLE
postgres=> 
postgres=> insert into tuniq(id, name) values(0, 'zero');
INSERT 0 1
postgres=> insert into tuniq(id, name) values(1, 'first');
INSERT 0 1
postgres=> insert into tuniq(id, name) values(2, 'second');
INSERT 0 1
postgres=> 
postgres=> select * from tuniq ;
 id |  name  
----+--------
  1 | first
  0 | zero
  2 | second
(3 rows)

这个数据已经导入完成,后续想让id键自增的话,需要先建一个sequence,并更新到最新的值:

postgres=> create sequence tuniq_id_seq;
CREATE SEQUENCE
postgres=> 
postgres=> select setval('tuniq_id_seq', max(id)) from tuniq;
 setval 
--------
      2
(1 row)

postgres=> 
postgres=> ALTER TABLE tuniq  ALTER id  set default nextval('tuniq_id_seq'::regclass);
ALTER TABLE

这个时候,就可以把sequence的值作为tuniq表id字段的默认值了,如:

postgres=> insert into tuniq(name) values('third');
INSERT 0 1
postgres=> 
postgres=> 
postgres=> select * from tuniq;
 id |  name  
----+--------
  1 | first
  3 | third
  0 | zero
  2 | second
(4 rows)

从以上我们可以看出,用PG/GP的自增需要注意:

  1. serial是通过sequence设置字段的默认值
  2. 可以考虑加上唯一约束,防止主动插入该字段的值,破坏该字段值的自增序和唯一性(如果业务关心的话)
目录
相关文章
|
敏捷开发 监控 安全
螺旋模型是什么?在软件开发中如何降低风险?
螺旋模型是一种结合了瀑布模型和快速原型模型的软件开发方法,强调风险分析的重要性。每个迭代周期包含计划制定、风险分析、工程实施和客户评估四个阶段,旨在通过持续的风险管理和客户反馈,提高软件质量和项目成功率。该模型由Barry Boehm于1988年提出,适用于需求不稳定、高风险的项目。
1004 4
|
移动开发 前端开发 JavaScript
大前端时代
大前端时代
272 1
|
机器学习/深度学习 人工智能 自然语言处理
人工智能与文本生成:基于Transformer的文本生成模型
人工智能与文本生成:基于Transformer的文本生成模型
|
5月前
|
机器学习/深度学习 算法 前端开发
集成电路设计:从概念到实现的完整解析优雅草卓伊凡
集成电路设计:从概念到实现的完整解析优雅草卓伊凡
261 2
集成电路设计:从概念到实现的完整解析优雅草卓伊凡
|
并行计算 大数据 数据处理
亿级数据处理,Pandas的高效策略
在大数据时代,数据量的爆炸性增长对处理技术提出更高要求。本文介绍如何利用Python的Pandas库及其配套工具高效处理亿级数据集,包括:采用Dask进行并行计算,分块读取以减少内存占用,利用数据库进行复杂查询,使用内存映射优化Pandas性能,以及借助PySpark实现分布式数据处理。通过这些方法,亿级数据处理变得简单高效,助力我们更好地挖掘数据价值。
572 1
|
搜索推荐 关系型数据库 MySQL
MySQL 模糊查询新纪元:超越 LIKE+% 的高效探索
在数据库的日常操作中,模糊查询是一项不可或缺的功能,它允许我们根据不完全匹配的关键字来检索数据。传统上,MySQL 使用 LIKE 关键字配合 % 通配符来实现这一功能,虽然灵活但性能上往往不尽如人意,尤其是在处理大型数据集时。今天,我们将一起探索几种超越 LIKE+% 的模糊查询技术,以提升查询效率与用户体验。
724 2
|
弹性计算 关系型数据库 数据库
PostgreSQL 数据库实例只读锁定(readonly) - 硬锁定,软锁定,解锁
标签 PostgreSQL , 只读 , 锁定 , readonly , recovery.conf , 恢复模式 , pg_is_in_revoery , default_transaction_read_only 背景 在一些场景中,可能要将数据库设置为只读模式。 例如, 1、云数据库,当使用的容量超过了购买的限制时。切换到只读(锁定)模式,确保用户不会用超。 2、业务上需要对
7596 0
|
缓存 前端开发 JavaScript
【JavaScript】JavaScript 中的闭包:从入门到精通
【JavaScript】JavaScript 中的闭包:从入门到精通
236 0
|
SQL Java 数据库连接
【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门
【MyBatis-Plus】快速精通Mybatis-plus框架—快速入门
642 0
|
JSON 监控 测试技术
Rabbmit MQ 清空所有Queue及其message
在测试区,经常因为测试导致测试区很多队列里面堆积很多消息。这一方面对测试区MQ的性能造成问题,dashboard这个插件经常卡主。此外消息过多也不方便debug。
2105 0