ICode9

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

数据库快速插入1000万条记录

2020-05-31 14:52:20  阅读:257  来源: 互联网

标签:String DB 数据库 visit value connection static 万条 1000


在实际的开发中,有些业务场景需要我们插入大量的测试数据,这时就考虑如何处理能够快速的插入。

现在去面试,偶尔也会遇到问:你会如何快速向数据插入1000万记录,这个问题我也被问道过,当时是没有回到上。其实很多东西没有用到,脑子被问到确实也没有idea。

 

处理分析:其实要想快速插入,无非就是两点

1、关闭数据自动提交,避免每次更新数据自动提交带来的时间损耗,改为手动提交。

2、批量插入处理,减少数据库连接带来的时间损耗次数。

 

处理方法:

1、编写存储过程进行处理。

2、编写Java程序进行处理。(身为Java开发人员,这种方式更友好,同时设置字段值也更加灵活方便)

  

大致处理说明:

这里使用的是MySQL,大致就是把语句拼接成如下形式,然后提交到数据库服务器;

insert into table_name
(field_1, field_2, ...,  field_n)
values
(value_11,value_12,..., value_1n),
(value_21,value_22,..., value_2n),
...
(value_n1,value_n2,..., value_nn)

 

注意:这里提交的数据量是有限制的,通过 show variables like '%max_allowed_packet%'; 默认大小是4M,提交的数量过大,就会报错。

我每次提交的数据量是10万条记录(需要提交100次),10万条记录对应的大小是12多M,报错了,然后把max_allowed_packet的大小设置成了20M。(通过my.ini进行改动,需要重启mysql)

 

代码如下:

DB工具类:

 

public class DBUtil {

    private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String DB_URL = "jdbc:mysql://localhost:3306/demos?serverTimezone=GMT%2B8&characterEncoding=utf8&useSSL=false&useUnicode=true";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "root";


    static {
        try {
            // 载入JDBC驱动程序  : 驱动器仅需要加载一次就可以了
            Class.forName(DB_DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接
     * @return
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
             connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    };

    /**
     * 关闭数据库连接
     * @param connection
     */
    public static void close(Connection connection) {
        if (connection!=null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
View Code

 

 

插入逻辑类:

public class DBInsertTest {

    public static void main(String[] args) {

        /*
            user_sex [1-2]
            user_province [1-34]
            user_area [1-10]
            visit_module[1-10]
            visit_function[60]
            visit_day[1-7]
        */
        // 记录开始时间
        Instant begin = Instant.now();

        // 获取数据库连接
        Connection connection = DBUtil.getConnection();
        String sqlPrefix = "insert into user_log(visit_name, visit_ip, user_sex, user_province, " +
                "user_area, visit_path, visit_module, visit_function, visit_day, visit_count, visit_time)" +
                "values";
        StringBuffer sqlSuffix = null;
        Random random = new Random();
        int day = 20200601;
        String[] hours = {"00", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
            "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "23"};
        try {
            // 设置事务为非自动提交
            connection.setAutoCommit(false);
            Statement statement = connection.createStatement();
            // 20*1000*50 20天 10000人 50条记录 = 1千万记录
            for(int i=0; i<100; i++) { // 100条记录 外层提交事务,20万记录提交一次,总共提交50次
                sqlSuffix = new StringBuffer();
                for(int j=0; j<10000; j++) { // 10000人
                    for(int k=0; k<10; k++) { // 10天
                        String visit_name = "name" + k + j;  //姓名
                        long visit_ip = 4294850663L; // IP
                        int user_sex = random.nextInt(2) + 1; // 性别
                        int user_province = random.nextInt(34) + 1; // 用户户籍区
                        int user_area = random.nextInt(10) + 1; // 用户注册区
                        String  visit_path = "https://blog.csdn.net/qq_31725371/article/details/83019856/xxxxxx";
                        int visit_module = random.nextInt(10) + 1; // 模块号
                        String visit_function = "function" + (random.nextInt(60) + 1); // 功能
                        int visit_day = random.nextInt(7) + 1; // 工作日
                        int visit_count = 5; // 同一路劲访问次数
                        long visit_time = Integer.parseInt(day+random.nextInt(20) + "" + hours[random.nextInt(24)]); // 访问时间
                        sqlSuffix.append("(")
                            .append("\'" + visit_name + "\'").append(",")
                            .append(visit_ip).append(",")
                            .append(user_sex).append(",")
                            .append(user_province).append(",")
                            .append(user_area).append(",")
                            .append("\'" + visit_path + "\'").append(",")
                            .append(visit_module).append(",")
                            .append("\'" + visit_function + "\'").append(",")
                            .append(visit_day).append(",")
                            .append(visit_count).append(",")
                            .append(visit_time).append("),");
                    }
                }
                // 构建完整SQL
                String sql = sqlPrefix + sqlSuffix.substring(0, sqlSuffix.length() - 1);
                //System.out.println("sql = " + sql);
                // 添加执行SQL
                statement.addBatch(sql);
                // 执行操作
                statement.executeBatch();
                // 提交事务
                connection.commit();
            }
            // 关闭连接
            statement.close();
            DBUtil.close(connection);
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }

        Instant end = Instant.now();
        System.out.println("1000万记录插入时间为:" + Duration.between(begin, end).getSeconds() + "s");

    }
}
View Code

 

插入时间:

 

标签:String,DB,数据库,visit,value,connection,static,万条,1000
来源: https://www.cnblogs.com/gangbalei/p/13016292.html

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

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

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

ICode9版权所有