测试数据生成工具

602 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

概述

前面对订单平台的业务场景进行了说明,分析了当业务数据大到一定程度的时候对系统效率 带来的影响以及不同的优化方案,在具体的方案中都有相应落地代码。

不管是在实际的业务开发中还是案例的学习中,需要尽量模拟生产环境的场景降低系统运行 的时候测试环境与生产环境的差异。

首先需要解决的就是生产真实数据量的问题。如果是已经运行一段时间的系统,生产上有比较 多的数据,可以对生产数据进行脱敏后导入到测试环境中;如果没有生产数据就需要手动创建 大批量数据。可以通过代码生成、常见的API工具批量调用接口、SQL脚本等方式生成测试数据。 本项目通过代码生成测试数据,对数据生成工具做一个简单的介绍和说明。

设计思路

  • 定义一个数据批量插入工具类,进行数据插入
  • 定义一个任务调用数据批量插入工具类
  • 多线程调用数据插入任务

关键类说明

  • InsertDataUtils: 批量插入数据工具类。
    • 管理数据库连接信息,并创建数据库连接
    • 拼接插入数据的SQL语句,生成PreparedStatement对象
    • 循环给预编译SQL设置参数并执行
  • Worker: 实现Runnable接口,循环调用InsertDataUtils插入数据
  • BatchInsert: 批量插入数据客户端,循环创建多个线程并执行Worker任务插入数据

落地代码

客户端没执行一次插入的数据量为: 总数据量 = BatchInsert的线程循环次数 * Worker的循环次数 * InsertDataUtils的循环次数

public class BatchInsert {
    public static void main(String[] args) {
        int threadCount = 100;
        int total = 100000;
        int every = total / threadCount;
        final CountDownLatch latch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new Thread(new Worker(latch, i * every, (i + 1) * every)).start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class Worker implements Runnable {

    int start = 0;
    int end = 0;
    CountDownLatch latch;

    public Worker(CountDownLatch latch, int start, int end) {
        this.start = start;
        this.end = end;
        this.latch = latch;
    }

    @Override
    public void run() {
        for (int i = start; i < end; i++) {
            InsertDataUtils insertDateUtils1 = new InsertDataUtils();
            insertDateUtils1.insertBigData3();
        }
        latch.countDown();
    }

}
public class InsertDataUtils {
    //起始id
    private long begin = 1;
    //每次循环插入的数据量
    private long end = begin+30;
    private String url = "jdbc:mysql://xx.xx.xx.xx:3306/monomer_order?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT";
    private String user = "root";
    private String password = "xxxx";
    //订单状态
    private Integer[] orderStatus = {10,20,30,40,50,55,60,70};
    //订单状态
    private Integer[] payStatus = {1,2,3};
    //配送状态
    private Integer[] deliveryStatus = {0,1,2,3};


    public void insertBigData3() {
        //定义连接、statement对象
        Connection conn ;
        PreparedStatement pstm ;
        PreparedStatement pstm2 ;
        PreparedStatement pstm3 ;
        PreparedStatement pstm4 ;
        PreparedStatement pstm5 ;
        try {
            //加载jdbc驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //连接mysql
            conn = DriverManager.getConnection(url, user, password);
            //将自动提交关闭
            conn.setAutoCommit(false);
            //编写sql
            String sql = "INSERT INTO `order_info` ( `order_no`, `order_amount`, `merchant_id`, `user_id`,`address_id`,`order_status`,pay_status,delivery_status,trans_time,recharge_time,update_time) VALUES (?,?,?,?,?,?,?,?,?,?,?);";
            String sql2 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
            String sql3 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
            String sql4 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";
            String sql5 ="INSERT INTO `order_item_detail` (`order_no`, `product_id`, `category_id`) VALUES (?,?,?)";

            //预编译sql
            pstm = conn.prepareStatement(sql);
            pstm2 = conn.prepareStatement(sql2);
            pstm3 = conn.prepareStatement(sql3);
            pstm4 = conn.prepareStatement(sql4);
            pstm5 = conn.prepareStatement(sql5);

            Long merId = CommonUtils.createNo(1000000000);
            for(int i=0;i<10;i++) {
                Long userId = CommonUtils.createNo(100000000);;
                //开始循环
                while (begin < end) {
                    Long no = CommonUtils.createNo(1000000000);
                    String orderCode = GenerateOrderNoUtils.getOrderNo(no,merId);
                    Long productId = CommonUtils.createNo(100000);
                    //赋值
                    pstm.setString(1, orderCode);
                    pstm.setBigDecimal(2, new BigDecimal(productId));
                    pstm.setLong(3, merId);
                    pstm.setLong(4, userId);
                    pstm.setLong(5, 2L);
                    pstm.setLong(6, CommonUtils.getStatus(Arrays.asList(orderStatus)));
                    pstm.setLong(7, CommonUtils.getStatus(Arrays.asList(payStatus)));
                    pstm.setLong(8, CommonUtils.getStatus(Arrays.asList(deliveryStatus)));
                    pstm.setDate(9, CommonUtils.getDate());
                    pstm.setDate(10, CommonUtils.getDate());
                    pstm.setDate(11, CommonUtils.getDate());
                    //执行sql
                    pstm.execute();

                    pstm2.setString(1, orderCode);
                    pstm2.setLong(2, productId);
                    pstm2.setLong(3, productId);
                    pstm2.execute();

                    pstm3.setString(1, orderCode);
                    pstm3.setLong(2, productId);
                    pstm3.setLong(3, productId);
                    pstm3.execute();

                    pstm4.setString(1, orderCode);
                    pstm4.setLong(2, productId);
                    pstm4.setLong(3, productId);
                    pstm4.execute();

                    pstm5.setString(1, orderCode);
                    pstm5.setLong(2, productId);
                    pstm5.setLong(3, productId);
                    pstm5.execute();


                    begin++;
                }
                //执行批处理
                pstm.executeBatch();
                //执行批处理
                pstm2.executeBatch();
                //执行批处理
                pstm3.executeBatch();
                //执行批处理
                pstm4.executeBatch();
                //执行批处理
                pstm5.executeBatch();

                //提交事务
                conn.commit();
                //边界值
                end += 30;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
    }
}

工作流程图

image-20220801164849432.png