天天看点

Greenplum merge insert 用法与性能 (insert on conflict)

PostgreSQL , Greenplum , merge insert , insert on conflict , 合并插入 , 有则更新 , 无则插入

PostgreSQL insert on conflict语法非常强大,支持合并写入(当违反某唯一约束时,冲突则更新,不冲突则写入),同时支持流式计算。

流计算例子链接:

<a href="https://github.com/digoal/blog/blob/master/201711/20171123_02.md">《PostgreSQL 流式统计 - insert on conflict 实现 流式 UV(distinct), min, max, avg, sum, count ...》</a>

<a href="https://github.com/digoal/blog/blob/master/201711/20171107_23.md">《HTAP数据库 PostgreSQL 场景与性能测试之 22 - (OLTP) merge insert|upsert|insert on conflict|合并写入》</a>

<a href="https://github.com/digoal/blog/blob/master/201704/20170424_04.md">《PostgreSQL upsert功能(insert on conflict do)的用法》</a>

<a href="https://github.com/digoal/blog/blob/master/201703/20170330_03.md">《PostgreSQL 10.0 preview 功能增强 - 支持分区表ON CONFLICT .. DO NOTHING》</a>

PostgreSQL insert on conflict语法如下:

Greenplum的版本较低,还不支持insert on conflict的语法。

如果需要在Greenplum中实现类似的功能该如何操作?

ID为PK,以它为合并列,举例。

1、目标表,也就是需要合并写入的目标:

2、中间表,也就是用户只管插入的表:

写入一些中间记录。

3、窗口合并,按唯一值约束,仅提取一条(可能存在窗口内合并的需求,例如按时间取最新,比如以最后一条为准,又或者以有值,且最新的为准)。

以有值切最新为准例子:

存储中间结果:

4、合并写入:

将窗口提取的结果,合并写入目标表。

4.1、INNER JOIN,覆盖旧记录,同时补齐旧的字段(以NULL为判断条件。如果新的记录没有值,则取旧记录的值。)提取。

4.2、DELETE USING,删除全量表的符合条件的记录。

4.3、INSERT

硬件:使用一台64线程机器,单机启动48个segment。

1、全量数据20亿。

2、增量数据1000万条,涉及500万个ID。

3、合并。

增量数据,窗口合并去重。

使用增量数据,提取并合并旧数据。

删除旧数据。

插入新增、以及合并的增量数据。

数据校验

4、合并总耗时:

<code>35秒</code>

5、耗时分布

增量数据1000万条,涉及500万个ID。

<code>4.5秒</code>

<code>5.2秒</code>

<code>9.5秒</code>

<code>15秒</code>

<code>0.7秒</code>

比较复杂、而且不支持新值使用NULL值(要支持的话,得修改一下覆盖逻辑)。

<a href="https://github.com/digoal/blog/blob/master/201711/20171127_01.md">《Greenplum 排序nulls first|last的 SQL写法实现》</a>

继续阅读