ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

【数据库】实现批量快速插入大量数据的六种方案

2022-09-14 20:33:52  阅读:219  来源: 互联网

标签:return String 批量 六种 数据库 int sql public conn


一、(MySQL)通过函数/存储过程

1、链接

https://www.jb51.net/article/207999.htm

https://blog.csdn.net/FloraCHY/article/details/117792903

2、代码

-- 进入数据库
use test;
-- 显示所有表
show tables;
-- 创建majors表
create table majors(id int, major varchar(255));
-- 定义结束符$
delimiter "$";
-- 创建存储过程,定义存储方法
create procedure batchInsert(in args int)
begin
declare i int default 1;
-- 开启事务(重要!不开的话,100w数据需要论天算)
start transaction;
while i <= args do
insert into majors(id,major) value(i,concat("软件工程-",i));
set i = i+ 1;
end while;
commit;
end
$
 
-- 调用函数,生成数据
-- 先生成10w条试试,同时输入$, 回车执行
call batchInsert(100000);
$

3、性能

10000条数据用了0.9s

100000条,5s执行完

100w条数据用了58s

二、通过jdbc的批量插入语句(add/executeBatch)

1、链接

http://t.zoukankan.com/lizm166-p-7890168.html

2、代码

    //获取要设置的Arp基准的List后,插入Arp基准表中    
    public boolean insertArpStandardList(List<ArpTable> list) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        //MySql的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
        //优化插入性能,用JDBC的addBatch方法,但是注意在连接字符串加上面写的参数。
        //例如: String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true" ;
        String sql = "insert into arp_standard(guid, devicebrand, devicename, deviceip, ipaddress, " +
                     "macaddress, createtime) values(?,?,?,?,?,?,?)";
        try{
            conn = DBConnection.getConnection();
            ps = conn.prepareStatement(sql);
            //优化插入第一步设置手动提交  
            conn.setAutoCommit(false); 
            int len = list.size();
            for(int i=0; i<len; i++) {
                ps.setString(1, list.get(i).getGuid());
                ps.setString(2, list.get(i).getDeviceBrand());
                ps.setString(3, list.get(i).getDeviceName());
                ps.setString(4, list.get(i).getDeviceIp());
                ps.setString(5, list.get(i).getIpAddress());
                ps.setString(6, list.get(i).getMacAddress());
                ps.setString(7, list.get(i).getCreateTime());
                //if(ps.executeUpdate() != 1) r = false;    优化后,不用传统的插入方法了。
                //优化插入第二步插入代码打包,等一定量后再一起插入。
                ps.addBatch(); 
                //if(ps.executeUpdate() != 1)result = false;
                //每200次提交一次 
                if((i!=0 && i%200==0) || i==len-1){//可以设置不同的大小;如50,100,200,500,1000等等  
                    ps.executeBatch();  
                    //优化插入第三步提交,批量插入数据库中。
                    conn.commit();  
                    ps.clearBatch();//提交后,Batch清空。
                }
            }
        } catch (Exception e) {
            System.out.println("MibTaskPack->getArpInfoList() error:" + e.getMessage());
            return false;   //出错才报false
        } finally {
            DBConnection.closeConection(conn, ps, rs);
        }
        return true;
    }

三、通过多线程执行jdbc过程

1、链接

http://t.zoukankan.com/fangts-p-6813515.html

2、代码

package tenThreadInsert;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
 
public class MyThread extends Thread{
                public void run() {
                     String url = "jdbc:mysql://127.0.0.1/teacher"; 
                     String name = "com.mysql.jdbc.Driver"; 
                     String user = "root"; 
                     String password = "123456"; 
                    Connection conn = null; 
                    try {
                        Class.forName(name);
                        conn = DriverManager.getConnection(url, user, password);//获取连接 
                        conn.setAutoCommit(false);//关闭自动提交,不然conn.commit()运行到这句会报错
                    } catch (ClassNotFoundException e1) {
                        e1.printStackTrace();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                // 开始时间
                Long begin = new Date().getTime();
                // sql前缀
                String prefix = "INSERT INTO test_teacher (t_name,t_password,sex,description,pic_url,school_name,regist_date,remark) VALUES ";
                try {
                    // 保存sql后缀
                    StringBuffer suffix = new StringBuffer();
                    // 设置事务为非自动提交
                    conn.setAutoCommit(false);
                    // 比起st,pst会更好些
                    PreparedStatement  pst = (PreparedStatement) conn.prepareStatement("");//准备执行语句
                    // 外层循环,总提交事务次数
                    for (int i = 1; i <= 10; i++) {
                        suffix = new StringBuffer();
                        // 第j次提交步长
                        for (int j = 1; j <= 100000; j++) {
                            // 构建SQL后缀
                            suffix.append("('" +i*j+"','123456'"+ ",'男'"+",'教师'"+",'www.bbb.com'"+",'Java大学'"+",'"+"2016-08-16 14:43:26"+"','备注'" +"),");
                        }
                        // 构建完整SQL
                        String sql = prefix + suffix.substring(0, suffix.length() - 1);
                        // 添加执行SQL
                        pst.addBatch(sql);
                        // 执行操作
                        pst.executeBatch();
                        // 提交事务
                        conn.commit();
                        // 清空上一次添加的数据
                        suffix = new StringBuffer();
                    }
                    // 头等连接
                    pst.close();
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                // 结束时间
                Long end = new Date().getTime();
                // 耗时
                System.out.println("100万条数据插入花费时间 : " + (end - begin) / 1000 + " s"+"  插入完成");
    }  
}
 测试代码

package tenThreadInsert;
 
public class Test {
 
    public static void main(String[] args) {
        for (int i = 1; i <=10; i++) {
              new MyThread().start();
            }
    }
 
}

四、一次性插入多条记录

1、原理

MySQL:

INSERT INTO Persons (LastName, Address) VALUES ('Wilson', 'Champs-Elysees'),('Gates', 'Champs-Elysees')

Oracle:

insert into 表名 (字段1)

select '1' from dual

union all

select '2' from dual

2、代码

(1)调用

public static Boolean insertManyByOne(int num) {
        String sql = GenSqlUtil.genInsManySql(num);
        // System.out.println(sql);
        jdbcUtils.insertMany(sql);
        System.out.println("共插入" + num + "条数据");
        return true;
    }


public static String genInsManySql(int num) {
        String sql = "INSERT INTO TEST.\"ABANK\"\n ";
        for (int i = 0; i < num; i++) {
            sql = sql.concat("select '1', 'CH', '9999', 'Zürcher Kantonalbank', " +
                    "'ZKBKCHZZ80A', ' ', TO_DATE('2009-11-10 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), " +
                    "TO_DATE('1599-12-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), " +
                    "TO_DATE('2017-07-12 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), " +
                    "'ADMIN', TO_DATE('1599-12-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), " +
                    "'ADMIN', TO_TIMESTAMP('2021-04-23 08:54:05.000', 'SYYYY-MM-DD HH24:MI:SS:FF3'), " +
                    "TO_TIMESTAMP('"+ dateFormat.format(calendar.getTime()) +
                    "', 'SYYYY-MM-DD HH24:MI:SS:FF3'), " +
                    "HEXTORAW('"+ RandNumGenUtil.genDefLenStr(15) +"') from dual");
            if (i != num -1) {
                sql = sql.concat("\n union all \n");
            }
        }
        return sql;
    }

(2)jdbcutils

package com.boulderaitech.utils;

import java.sql.*;
import java.util.Arrays;

public class JDBCUtil {
    private String user;
    private String pass;
    private String url;

    private Connection conn = null;//连接对象
    private ResultSet rs = null;//结果集对象
    private Statement sm = null;

    /**
     * 构造函数获得数据库用户名和密码
     *
     * @param user
     * @param pass
     */
    public JDBCUtil(String user, String pass) {
        this.user = user;
        this.pass = pass;
        this.url = "jdbc:oracle:thin:@//172.16.5.162:1521/helowin";
    }

    /**
     * 连接数据库
     *
     * @return
     */
    public Connection createConnection() {
        String sDBDriver = "oracle.jdbc.driver.OracleDriver";
        try {
            Class.forName(sDBDriver).newInstance();
            conn = DriverManager.getConnection(url, user, pass);
        } catch (Exception e) {
            System.out.println("数据库连接失败");
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭数据库
     *
     * @param conn
     */
    public void closeConnection(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            System.out.println("数据库关闭失败");
            e.printStackTrace();
        }
    }

    /**
     * 插入数据
     *
     * @param insert 插入语句
     * @return
     */
    public int insert(String insert) {
        conn = createConnection();
        //String insert = "insert into t_department values('D004','金融部')";
        int re = 0;
        try {
            conn.setAutoCommit(false);//事物开始

            sm = conn.createStatement();
            re = sm.executeUpdate(insert);
            if (re < 0) {               //插入失败
                conn.rollback();      //回滚
                sm.close();
                closeConnection(conn);
                return re;
            }
            conn.commit();            //插入正常
            sm.close();
            closeConnection(conn);
            return re;
        } catch (Exception e) {
            e.printStackTrace();
        }
        closeConnection(conn);
        return 0;
    }

    /**
     * 批量插入数据
     */
    public int insertBatch(String[] sql) {
        conn = createConnection();
        //String insert = "insert into t_department values('D004','金融部')";
        int re = 0;
        try {
            conn.setAutoCommit(false);//事务开始
            sm = conn.createStatement();
            Arrays.stream(sql).forEach(x->{
                try {
                    sm.executeUpdate(x);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            });
            conn.commit();            //插入正常
            sm.close();
            closeConnection(conn);
            return re;
        } catch (Exception e) {
            e.printStackTrace();
        }
        closeConnection(conn);
        return 0;
    }

    /**
     * 查询语句
     * 返回结果集
     *
     * @param select
     * @return
     */
    public ResultSet selectSql(String select) {
        conn = createConnection();
        try {
            sm = conn.createStatement();
            rs = sm.executeQuery(select);
            return rs;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据结果集输出
     *
     * @param rs
     */
    public void printRs(ResultSet rs) {
        int columnsCount = 0;
        boolean f = false;
        try {
            if (!rs.next()) {
                return;
            }
            ResultSetMetaData rsmd = rs.getMetaData();
            columnsCount = rsmd.getColumnCount();//数据集的列数
            for (int i = 0; i < columnsCount; i++) {
                System.out.print(rsmd.getColumnLabel(i + 1) + "/n"); //输出列名
            }
            System.out.println();

            while (!f) {
                for (int i = 1; i <= columnsCount; i++) {
                    //System.out.print(rs.getString(i)+"/t");
                    //逻辑处理
                    String name = rs.getString("NAME");

                    System.out.print(rs.getString("NAME") + "/n");
                }
                System.out.println();
                if (!rs.next()) {
                    f = true;
                }
            }
            rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        closeConnection(conn);
    }

    /**
     * 插入数据
     *
     * @param update 更新语句
     * @return
     */
    public int update(String update) {
        conn = createConnection();
        //String insert = "insert into t_department values('D004','金融部')";
        int re = 0;
        try {
            conn.setAutoCommit(false);//事物开始

            sm = conn.createStatement();
            re = sm.executeUpdate(update);
            if (re < 0) {               //插入失败
                conn.rollback();      //回滚
                sm.close();
                closeConnection(conn);
                return re;
            }
            conn.commit();            //插入正常
            sm.close();
            closeConnection(conn);
            return re;
        } catch (Exception e) {
            e.printStackTrace();
        }
        closeConnection(conn);
        return 0;
    }

    public int insertMany(String sql) {
        conn = createConnection();
        int re = 0;
        try {
            conn.setAutoCommit(false);//事物开始

            sm = conn.createStatement();
            re = sm.executeUpdate(sql);
            if (re < 0) {               //插入失败
                conn.rollback();      //回滚
                sm.close();
                closeConnection(conn);
                return re;
            }
            conn.commit();            //插入正常
            sm.close();
            closeConnection(conn);
            return re;
        } catch (Exception e) {
            e.printStackTrace();
        }
        closeConnection(conn);
        return 0;
    }
}

五、通过定时器实现定时执行

public static Boolean insertBatchFixTime(int numOfInsert, int timePerEpoch) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                insertManyByOne(numOfInsert);
            }
        }, 0L, timePerEpoch * 1000L);
        System.out.println("当前线程:" + Thread.currentThread().getName() + " 当前时间" + LocalDateTime.now());
        return true;
    }

六、通过循环实现批量插入

public static Boolean insertBatchFixCircle(int numOfEachInsert, int numOfEpoch) {
        LocalDateTime start = LocalDateTime.now();
        for (int i = 0; i < numOfEpoch; i++) {
            insertManyByOne(numOfEachInsert);
        }
        System.out.println("共插入" + numOfEachInsert * numOfEpoch+"条数据");
        LocalDateTime end = LocalDateTime.now();
        System.out.println("共耗时" + Duration.between(start, end).toMillis() + "ms");
        return true;
    }

 

标签:return,String,批量,六种,数据库,int,sql,public,conn
来源: https://www.cnblogs.com/liujinhui/p/16694380.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有