ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Greenplum的导出效率问题

Greenplum的导出效率问题

Linux操作系统 作者:feng_whut 时间:2014-06-16 17:34:18 0 删除 编辑
声明:转载必须注明出处
      GP的数据导出不应当包含gp_dump,其是一个shell命令,且导出的文件中还包含了恢复时需要的脚本,不属于纯数据文件。
真正可以作为导出数据使用的方法有:可写外部表和Copy,这两种方式也存在一些差异,本文主要讨论两者之间如何选择。
     先说说Copy这个SQL命令,Copy有两种选择:Copy一个表对象|COPY一个查询,两者在性能上有显著的差异,笔者猜测可能
与二者的实现有关,对一个表对象直接做Copy操作时,可以将单个文件的写性能发挥到极致,一般可以达到300~400MB/S范围,
近乎单文件读写的CPU性能极限。此时使用系统工具也可以看到,有一个CPU的Core达到了100%的繁忙程度。这绝对是使用者所
期待的,也是Copy整表的优势。Copy作用在一个查询上时,性能有大幅下降,大约在70MB/S,差不多是作用在整表上时性能的
20%,时间被无情的拉长了4倍。因此,Copy更适合整表操作,如果必须要作用在查询语句上,笔者建议:先根据查询生成一个中
间结果表,再将中间结果表Copy出去。
     不过,Copy命令本身是没有并发的,因此,对于GP这样的MPP环境来说,绝对不足以应付所有场合,对于超大规模数据需要
被导出的场景很不适合。对于那些较小规模的导出,比如100GB左右的导出,Copy是一个很不错的简单快捷的选择。
     再来说说可写外部表,可写外部表与可读外部表都基于gpfdist服务,而性能与可读外部表确有较大差异,单个gpfdist服务的
可读外部表可以达到300~400MB/S的范围,而单个gpfdist服务的可写外部表性能表现较差,笔者没记错的话,与Copy作用在查询
上的性能相当70MB/S左右。不过,在实际应用中,可以使用多个gpfdist配合多个输出文件来提升性能。
      下面贴出笔者曾今用Python写的GP Function,用以同时直接连接Segment Instance做Copy导出的代码,由于代码写得时间
稍有些久远,仅作为参考,不完善之处还请包含。该函数借鉴了gp_dump的思路,每个Instance做一份独立的Copy操作,从而确
保性能可以达到极限。
     注:如果直接导出到Master上,可能会产生网络拥堵,需慎用。笔者已经考虑重写这方面的函数,用以实现导出到集群外的机
器上,但目前还只在考虑阶段,实现思路在下面的代码中已经完全体现,有兴趣者可以尝试自行实现。至于使用什么语言,笔者认
为,Python或者Perl都是不错的选择。

点击(此处)折叠或打开

  1. create or replace function gp_toolkit.gp_direct_export(table_name text, delimiter_char char,
    directory text,file_pre text, file_tail text,file_format text, batch_size int, is_on_master boolean)
    returns setof text as
    $body$
    import os
    import time
    import thread
    import threading
    dbsnm=plpy.execute("select current_database() as dbn")[0]["dbn"]
    tblnm=table_name
    dlmtr=delimiter_char
    drcts=directory.split(',')
    tmspn=1.0/batch_size
    onmst=is_on_master
    flpre=file_pre
    fltal=file_tail
    flfmt=''
    if file_format.lower()=='csv':
        flfmt='csv'
    def thread_copy(cont,addr,port,drct):
        cmr="PGOPTIONS='-c gp_session_role=utility' psql -h "+addr+" -d "+dbsnm+" -p "+port+" <     if onmst:
            cmr=cmr+r'\copy '
        else:
            cmr=cmr+r'copy '
        cmr=cmr+tblnm+" to '"+drct+"/"+flpre+"_"+cont+"."+fltal+"' delimiter '"+dlmtr+"' "+flfmt+""
        cmr=cmr+"\nEOF"
        os.popen(cmr)
        thread.exit()
    segments_sql="select content::text c,address::text a,port::text p from gp_segment_configuration where content<>'-1' and role<>'m'"
    segments_row=plpy.execute(segments_sql)
    thread_pool=[]
    idx=0
    lth=len(drcts)
    for seg_row in segments_row:
        th=threading.Thread(target=thread_copy,args=(seg_row['c'],seg_row['a'],seg_row['p'],drcts[idx]))
        thread_pool.append(th)
        idx=idx+1
        if idx==lth:
            idx=0
    yield('START COPY...')
    lth=len(thread_pool)
    idx=1
    for th in thread_pool:
        th.start()
        if idx         time.sleep(tmspn)
            idx=idx+1
    for th in thread_pool:
        th.join()
    yield('COPY COMPLETE...')
    $body$
    language plpythonu volatile;
声明:转载必须注明出处

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10109602/viewspace-1184090/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2014-06-16

  • 博文量
    25
  • 访问量
    68896