GreenPlum及PostgreSQL使用CopyManager装载数据

19 篇文章 0 订阅
4 篇文章 0 订阅

   

目录

CopyManager基本用法

日期及时间类型处理方式

Numeric类型处理方式


我们在使用数据库时经常会遇到需要进行数据导入导出的操作,近期使用刚好用到了GreenPlum,因为GreenPlum实际就是对PostgreSQL的封装,所以此经验适用于PostgreSQL及GreenPlum。

在PostgreSQL中装载数据有CopyManager、GpLoad、GreenPlum-Spark-Connector、GpfDist等多种方式,其中GpLoad、GreenPlum-Spark-Connector其实是基于GpfDist来实现的,CopyManager则是依赖于PG的驱动来实现,这里先把CopyManager的基本用法和使用中遇到的问题做个记录。

CopyManager基本用法

这里是copy命令的官方说明,从copy的官方说明可以看出支持将数据通过text、csv以及binary格式的文件进行导入,其中text、csv都是文本文件,因此也会产生一个问题就是如果字段内容是byte数据则无法处理,当数据字符串中存在字符与文本文件中字段分隔符或换行符重复的字符时也会产生问题,因此用binary是最好的解决办法。

binary格式导入的基本用法如下:

String sql = "COPY public.test(a,b,c) FROM STDIN BINARY");
PGCopyOutputStream pgCopyOutputStream = new PGCopyOutputStream(conn, sql);
DataOutputStream os = new DataOutputStream(pgCopyOutputStream);
byte[] header = {'P', 'G', 'C', 'O', 'P', 'Y', '\n', (byte) 0xFF, '\r', '\n', '\0'};
os.write(header );
if (hasOid) {
    os.writeInt(0);
} else {
    os.writeInt(1);
}
os.writeInt(0);

for(int i = 0; 0 < rows.size(); i++) {
    os.writeShort(3); //导入字段数
    for (int j = 0; j < 3; j++) {
        if(colValue == null){
            os.writeInt(-1); //对应字段无值
        }else{
            os.writeInt(colLength); //对应字段长度
            os.write(colValue); //对应字段值
        }
    }
}
os.writeShort(-1);
os.flush();
os.close();
conn.commit();

注意点:

1、在上边的代码中conn必须是PgConnnection,如果是用了druid等数据库连接池则需要从相关数据源中拿出原始GpConnection。

2、当某个字段无值时直接在字段长度中写入-1,字段值中不需要写入任何数据。

3、不同类型对应字段长度不同,如short为2、int4为4,int8为8,long为8,double为8,float为4,String为字符串转为byte[]的长度,numeric为8+gpNumeric.getLen()*2。

4、在写字段值时根据不同类型写入方式不同,如int需用writeInt(int),long用writeLong(long),String用write(sting.getBytes())。

5、当conn设置了不自动提交则需要手工提交,手工提交代码需放在os.close()之后,否则会造成锁表。

日期及时间类型处理方式

对于日期及时间类型比较特殊:

Date:该类型需要计算出所设置日期与2000-01-01的天数间隔,以int写入。

Timestamp:该类型需要计算出所设置时间与2000-01-01 00:00:00.000的毫秒间隔*1000,以long写入。

Time:该类型需要计算出所设置时间与00:00:00.000的毫秒间隔*1000,以long写入。

Numeric类型处理方式

当表字段中存在numeric类型的字段时处理比较特殊,其中需要用到的GpNumeric详见GpNumeric

GpNumeric gpNumeric = new GpNumeric(String.valueOf(srcValue));
os.writeInt(8+gpNumeric.getLen()*2);
os.writeShort(gpNumeric.getLen());
os.writeShort(gpNumeric.getWeight());
os.writeShort(gpNumeric.getSig());
os.writeShort(gpNumeric.getScale());
for(short s : gpNumeric.toShortArray()){
    os.writeShort(s);
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EngineZhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值