如何高效的使用java向mysql插入1-10W条数据

假设表字段 id(自增),标题,图片地址,视频地址,热度,创建时间,更新时间
如何高效的使用java向mysql插入1-10W条数据
我目前是 查询出数据遍历集合,一条一条的插入表中,一开始插入1W条的时候每秒大概能插入几百上千条,现在表中有30W条数据,再次插入1W条数据的时候每秒只能插入几条数据,插入1W条 大概用了30-40分钟,而且cpu直接爆表, 一开始服务器是8h16g的,后来升级到16h32g,再次插入还是出现同样的问题,不知道问题出在哪里

因为接口超时的原因,使用了多线程

img

你循环一条一条的插入,肯定会原来越慢,应该分批插入,比如一批1000条,1万条,就10批

注意我的问题,最好能解释 为什么cpu会爆,并贴出你的代码,谢谢

原因:
1.for循环中每次循环查询数据库;
2.插入数据为单条插入;
这样频繁操作数据库,所以会相当耗资源的。

建议:
1.可以把for循环中的查询提取出来,改为一次性查出所有,然后再去循环list
2.单条插入改成批量插入
3.可以使用多线程

下面代码仅供参考:

package com.hky;

import com.hky.service.AgentVideo;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;


/**
 *
 * @author hky
 */
public class Test {

    private ForkJoinPool pool;

    public Test() {
        pool = new ForkJoinPool();
    }

    // 执行任务RecursiveTask:有返回值  RecursiveAction:无返回值
    private static class SumTask extends RecursiveTask<Long> {
        /**
         *
         */
        private static final long serialVersionUID = 1L;
        private List<PublicDailiVideo> numbers;
        private int from;
        private int to;

        public SumTask(List<PublicDailiVideo> numbers, int from, int to) {
            this.numbers = numbers;
            this.from = from;
            this.to = to;
        }

        // 此方法为ForkJoin的核心方法:对任务进行拆分  拆分的好坏决定了效率的高低
        @Override
        protected Long compute() {
            if (to - from < 1000) {
                List<PublicDailiVideo> list = numbers.subList(from, to);
                List<AgentVideo> agentVideoList = new ArrayList<>();
                // 准备要批量插入的list
                list.forEach(a -> {
                    AgentVideo agent = new AgentVideo();
                    agent.setName(a.getName());
                    agent.setImageUrl(a.getImageUrl());
                    agent.setVideoUrl(a.getVideoUrl());
                    agentVideoList.add(agent);
                });
                System.out.println("agentVideoList:" + agentVideoList.size());
                // TODO 批量插入数据
                System.out.println("批量插入数据:" + agentVideoList.size() + "条");

                return (long) agentVideoList.size();
            } else {
                int middle = (from + to) / 2;
                System.out.println("from:" + from + ",to:" + to + ",middle:" + middle);
                SumTask task1 = new SumTask(numbers, from, middle);
                SumTask task2 = new SumTask(numbers, middle, to);

                task1.fork();
                task2.fork();
                return task1.join() + task2.join();
            }
        }
    }

    public long sumUp(List<PublicDailiVideo> numbers) {
        Long res = pool.invoke(new SumTask(numbers, 0, numbers.size()));

        System.out.println("线程池大小" + pool.getPoolSize());
        pool.shutdown();
        return res;
    }

    public static void main(String[] args) {
        // 待循环的list
        List<PublicDailiVideo> publicdiliList = new ArrayList<PublicDailiVideo>();
        for (int i = 0; i < 10000; i++) {
            PublicDailiVideo video = new PublicDailiVideo();
            video.setName("ming" + i);
            video.setImageUrl("imageUrl" + i);
            video.setId(i + "");
            video.setVideoUrl("videoUrl" + i);
            publicdiliList.add(video);
        }
        System.out.println(publicdiliList.size());
        // 下面对应你pulbicVideoMapper.selectPublicVideoById()
        List<String> ids = publicdiliList.stream().map(PublicDailiVideo::getId).collect(Collectors.toList());

        // TODO 然后根据ids查询 AgentVideo的list,
        // 把查到的VideoUrl set到 publicdiliList 的中,这样就不需要你在for循环中,每循环一次就去查一次数据库了


        Instant now = Instant.now();

        Test calculator = new Test();
        long result = calculator.sumUp(publicdiliList);

        Instant end = Instant.now();

        System.out.println("耗时:" + Duration.between(now, end).toMillis() + "ms");
        System.out.println("结果为:" + result);
    }
}


循环查的话太频繁,一直在与数据库进行交互,cpu再大都没用,建议用批量插入,java有这个功能