Greenplum批量操作,數據庫裏面作刪除更新速度最快

這是記一次線上GP大數據庫 大量重複問題解決方案  1 建臨時表,把重複的數據備份,2 在備份庫用查詢條件去刪除正式表

 最近在玩Greenplum 數據庫, 一款分佈式的數據庫 ,MPP架構,但是有好的也有不如意的,總體感覺還是不錯,底層數據庫還是用PostgreSQL8.2版本, 因爲我是GP4.2嘛, 最新版本的GP6.0是基本PostgreSQL9.2,在性能上提高了不少。

 先說下,遇到的坑和一些數據問題,刪除數據和更新數據, 分區表等一些概念

補充 :今天發現JDBC提交數據的時候,數據庫報內存溢出,解決辦法是,兩次提交轉爲單條提交,批量3000條,全成一個批次提交,內存會爆點,好處是數據一致性得到保證,最後只能拆開作兩次保存,kafka積壓太多數據了,然後正常消費


   conn = JdbcUtil.getConnection();
            PreparedStatement pst = conn.prepareStatement(sql);
            pst.executeUpdate();

            PreparedStatement pstsql = conn.prepareStatement(sql2);
            pstsql.executeUpdate();
           /* PreparedStatement pstsql = conn.prepareStatement(sql2);
            pstsql.executeUpdate();*/
            conn.commit();
            pst.clearBatch();
            pstsql.clearBatch();
            /* pstsql.clearBatch();*/

依賴  放在項目的lib下面

    <dependency>
            <groupId>com.fbcds</groupId>
            <artifactId>fbcds</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/greenplum.jar</systemPath>
        </dependency>

手動加載包  打包到容器的時候,找不到驅動

第一步 下載greenplum.jar
    下載地址 http://download.csdn.net/download/enterings/10039723?web=web
第二步 在maven中手動添加本地jar包
    在 cmd命令行中 運行
    mvn install:install-file   -Dfile=D:\maven\greenplum.jar -DgroupId=com.huicai  -DartifactId=greenplum -Dversion=1.0  -Dpackaging=jar
   上面的命令解釋:
    -Dfile:指明你下載的jar包的位置(就是本地存放jar的路徑+jar包名);
    -DgroupId, -DartifactId,  -Dversion:三個參數,就是指明瞭存放maven倉庫中的位置;
    -Dpackaging :猜測就是指明文件類型;
第三步 pom.xml添加配置並重新 install maven
    該jar包的引用即可:
    <!-- greenplum -->
    <dependency>
      <groupId>com.huicai</groupId>
      <artifactId>greenplum</artifactId>
      <version>1.0</version>
    </dependency>

連接數據庫,當然還有其它的方法查詢封裝

// 餓漢式
    private static DruidDataSource dataSource = null;

    static {
        dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.pivotal.jdbc.GreenplumDriver");
        dataSource.setUsername("gptest");
         dataSource.setPassword("123456“);
     dataSource.setUrl("jdbc:pivotal:greenplum://192.168.0.1:8088;DatabaseName=npp_db");

        dataSource.setInitialSize(10);
        dataSource.setMinIdle(10);
        dataSource.setMaxActive(50); // 啓用監控統計功能
        dataSource.setTimeBetweenEvictionRunsMillis(300000);
        dataSource.setValidationQuery("SELECT 'x'");
        // 配置一個連接在池中最小生存的時間,單位是毫秒
        dataSource.setMinEvictableIdleTimeMillis(300000);


    }

 

批量操作代碼  主要是爲了操作線上數據,因爲有大量重複,分區表處理起來,超級麻煩,就先建臨時表保存要刪除的數據,

然後,利用數據庫相關性,先查詢臨時表的ID再去刪除正式表,操作與同插入的方式,在數據庫內部進行操作,速度會快很多,解決思路就是如此,在數據庫裏作刪除,而不是取到程序裏再操作,  

解決問題的思路很重要,要去套用哪種處理方式最快。

String tablename = Snmp_Table;
        String sql_info =
                " insert into da_his.test_five_data_his_1 select min(\"id\") \"id\",min(\"timestamp\") as \"timestamp\",max(snmp_index) "
                        + "as snmp_index,max(snmp) as snmp,max(\"in\") as \"in\",max(\"out\") as \"out\"  from " + tablename
                        + " where \"timestamp\">=? " + " and \"timestamp\"<=? and  (" + sl.toString()
                        + ") and \"in\"<'1250000000000' and  \"out\"<'1250000000000' group by "
                        + "\"timestamp\" ,snmp_index  having count(\"timestamp\")>1 ";
        //List<Map<String, Object>> list_info = (List<Map<String, Object>>) Gp_tools.query(sql_info, new Object[] {obj[0], obj[1]},
        //       new AllObjectMapper());
        Gp_tools.updateTemp(sql_info, new Object[] {obj[0], obj[1]}, true);

 public static boolean updateTemp(String sql, Object[] obj, boolean isGenerateKey) {
        Connection conn = null;

        boolean bFlag = true;
        try {
            conn = JdbcUtil.getConnection();
            PreparedStatement pstmt = conn.prepareStatement(sql);
           /* for (int i = 0; i < obj.length; i++) {
                pstmt.setObject(i + 1, obj[i]);
            }*/
            pstmt.setObject(1, obj[0]);
            pstmt.setObject(2, obj[1]);
            pstmt.executeUpdate();
            conn.commit();
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                JdbcUtil.releaseConnection(conn);
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
        return bFlag;
    }

另外的批量刪除, 操作也很慢

delete from da_his.tb_dev_five_data_1 as devfive using (values ('877|54',277,1444413654),('877|54',277,1444425009),('877|54',277,1444413674)) as tmp(snmp_index,snmp,"id") where 
 devfive.snmp_index=tmp.snmp_index and devfive.snmp=tmp.snmp and devfive.id=tmp.id ;  

批量更新操作,原理是一樣的, 但是在數據量幾十億又分成幾百個分區, 這種操作分分鐘能搞崩掉

 update test set info=tmp.info from (values (1,'new1'),(2,'new2'),(6,'new6')) as tmp (id,info) where test.id=tmp.id; 

批量刪除有可能如下 官網解釋的,最後group by id字段必須是唯一

DELETE FROM test
WHERE ctid NOT IN (
SELECT min(ctid)
FROM test
GROUP BY x);
(where 'x' is the unique column list)

 

最張解決方案  從臨時表的備份表查詢要刪除的數據,程序裏拼接下面的SQL

delete from da_his.tb_dev_five_data_1  where snmp=472 and "id" in(5357929218,5357927657,5357929285,5357928550,5357929262);

多線程跑起來,很快, 可能晚上用的人少,刪除非常快

發佈了144 篇原創文章 · 獲贊 28 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章