一、(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:
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\" ";
- 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(" union all \");
- }
- }
- 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;
- }