IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> PreparedStatement实现批量插入 -> 正文阅读

[大数据]PreparedStatement实现批量插入

问题引入

假如我们要通过JDBC实现插入大量数据,如果只是普通的插入方法要消耗大量时间,下面我们将同通过两个方面进行改进减少程序运行时间

普通方法

public void test1() {

        MyConnection myConnection = new MyConnection();
        Connection con = myConnection.getMyConnection();
        PreparedStatement ps = null;
        try {
            long start = System.currentTimeMillis();
            String insert = "insert into number(num) values(?);";
            ps = con.prepareStatement(insert);//预编译
            //插入1W条数据
            for (int i = 0; i < 10000; i++) {
                ps.setInt(1, (i+1));//设置属性值
                ps.executeUpdate();//执行SQL语句
            }

            long end = System.currentTimeMillis();

            System.out.println("消耗时间:"+(end-start));//23531  1W条
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            myConnection.closeAll(con, ps);//关闭连接
        }

    }

因为连接数据库开始的步骤基本都是死步骤,因此为了避免麻烦我就把部分代码封装进了MyConnection类中,方面获得Connection对象和断开连接

MyConnection

public class MyConnection {

    private Connection con = null;
    private PreparedStatement ps = null;
    private ResultSet rs = null;

    private String driver = "com.mysql.cj.jdbc.Driver";
    private String url = "jdbc:mysql://localhost:3306/xk";
    private String user = "root";
    private String password = "123456";

    public MyConnection() {

    }

    public Connection getMyConnection() {
        try {


            Class.forName(driver);

            con = DriverManager.getConnection(url,user,password);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (con != null) {
                System.out.println("数据库连接成功!");
            } else {
                System.out.println("数据库连接失败!");
            }
            return con;
        }
    }

    public void closeAll(Connection connection) {
        try {
            if (connection != null) connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    public void closeAll(Connection connection, PreparedStatement preparedStatement) {
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    public void closeAll(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

输出结果
在这里插入图片描述
在这里插入图片描述

1W条数据插入花费23972毫秒

改进方式一

在上述方法中,我们地SQL语句是一条一条执行的
在这里插入图片描述)

这样子就像是我们吃瓜子时剥一个吃一个,这样不是很浪费时间(毕竟我们要一个一个放进嘴里,当瓜子多的时候就很麻烦)于是我们就可以考虑等剥到一定量的瓜子然后一起放进嘴里

解决方式:攒sql语句

1.攒SQL语句–addBatch
2.执行Batch–executeBatch
3.清空Batch–clearBatch
注意: MySql服务器默认关闭批处理的,我们需要通过一个参数,让MySQL开启批处理的支持:?rewriteBatchedStatements=true(补充在url的后面)

MyConnection2 myConnection = new MyConnection2();
        Connection con = myConnection.getMyConnection();
        PreparedStatement ps = null;
        try {
            long start = System.currentTimeMillis();
            String insert = "insert into number(num) values(?)";
            ps = con.prepareStatement(insert);//预编译
            //插入10W条数据
            for (int i = 0; i < 100000; i++) {
                ps.setInt(1, (i+1));//设置属性值

                //攒SQL语句
                ps.addBatch();
                //攒够500条执行一次
                if ((i+1)%500 == 0) {
                    //执行SQL语句
                    ps.executeBatch();
                    //清空batch
                    ps.clearBatch();
                }
            }

            long end = System.currentTimeMillis();

            System.out.println("消耗时间:"+(end-start));//2480 --10W条
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            myConnection.closeAll(con, ps);//关闭连接
        }

注意
这里我是通过MyConnection2获得的Connection对象,MyConnection2和MyConnection的差别
在这里插入图片描述
输出结果
在这里插入图片描述
在这里插入图片描述
我们可以看出明显的差距这次插入10w条数据仅用了2459毫秒也就2秒多点

你以为这就完了吗,不我们还有压榨空间!

首先我们了解一下数据库的DDL、DML
DML: (Data Manipulation Language) 数据操纵语言(用来查询与更新记录): 就是UPDATE、INSERT、DELETE。
DDL:( Data Definition Language) 数据定义语言(用来定义数据库结构):CREATE 、ALTER、DROP。
DCL: (Data Control Language)数据控制语言(用来控制数据库的访问):grant; revoke; commit; rollback; lock。


然后我们要了解什么是事务
一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。


注意
??当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
??也就是说我们没执行一个插入的SQL语句都会提交一次事务,就相当于我们每嚼一次瓜子就咽进肚子,如果我们可以等所有瓜子嚼完一起咽岂不是很省事。

    @Test
    public void test3() {
        MyConnection2 myConnection2 = new MyConnection2();
        Connection con = myConnection2.getMyConnection();
        PreparedStatement ps = null;

        try {
            long start = System.currentTimeMillis();
            //不允许自动提交,这是我们首先要做的
            con.setAutoCommit(false);

            String insert = "insert into number(num) values(?)";

            ps = con.prepareStatement(insert);
			//下面的步骤跟前免得改进方式一一样
            for (int i = 1; i <= 100000; i++) {
                ps.setInt(1, i);
                ps.addBatch();
                if(i%500 == 0) {
                    ps.executeBatch();
                    ps.clearBatch();
                }
            }
            con.commit();

            long end = System.currentTimeMillis();
            System.out.println("消耗:"+(end-start));//2069 --10W
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            myConnection2.closeAll(con, ps);
        }
    }
}

输出结果
在这里插入图片描述
对比上面的方法这次10W条数据用了1.9秒


最后用通俗的话描述一下我们的改进过程

正常情况下我们吃瓜子步骤:
1.剥一个
2.放嘴巴里,嚼一嚼
3.咽下去

改进一:
1.剥指定数量瓜子
2.放嘴巴里,嚼一嚼
3.咽下去

改进二:
1.剥指定数量瓜子
2.剥完一波放嘴巴里嚼但是不咽
3.等所有瓜子嚼完后一起咽
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 10:48:29  更:2021-09-08 10:50:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 12:21:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码