很多同学都有这样的困扰

  • 工作中项目的数据量不大,遇不到sql优化的场景:单表就几万,我优化个der啊;
  • 业务对性能要求不高,远远没达到性能瓶颈:咱这项目又不是不能跑,优化个der啊;

确实,如果你的项目体量不大,不管是数据层还是应用层,都很难接触到性能优化

但是

我们可以自己造数据啊

今天我带来了一个demo,不仅让你能把多线程运用到实际项目中,还能用它往数据库造测试数据,让你体验下大数据量的表优化

定个小目标,今天造它一亿条数据

首先搞清楚,不要为了用技术而用技术,技术一定是为了实现需求:

  • 插入一亿条数据,这是需求;
  • 为了提高效率,运用多线程异步插入,这是方案;

1、为了尽可能模拟真实场景,我们new个对象

靠phone和createTime俩字段,能大大降低数据重复度,抛开别的字段不说,这俩字段基本能保证没有重复数据,所以我们最终的数据很真实,没有一条是重复的,而且,最后还能通过createTime来统计每秒插入条数,nice~

public class Person {private Long id;private String name;//姓名private Long phone;//电话private BigDecimal salary;//薪水private String company;//公司private Integer ifSingle;//是否单身private Integer sex;//性别private String address;//住址private LocalDateTime createTime;private String createUser;
}

2、想要插的更快,我们得使用MyISAM引擎,并且要主键自增(不知道为什么的兄弟私聊我或者评论区留言,咱们今天主题不是讲数据库本身)

ddl:

CREATE TABLE `person` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`salary` decimal(10,2) NOT NULL,`company` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`if_single` tinyint NOT NULL,`sex` tinyint NOT NULL,`address` varchar(225) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`create_time` datetime NOT NULL,`create_user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=30170001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

3、为了模拟真实数据,我们得用到一些枚举值和随机算法

部分属性枚举值:

private String[] names = {"黄某人", "负债程序猿", "谭sir", "郭德纲", "蔡徐鸡", "蔡徐老母鸡", "李狗蛋", "铁蛋", "赵铁柱"};
private String[] addrs = {"二仙桥", "成华大道", "春熙路", "锦里", "宽窄巷子", "双子塔", "天府大道", "软件园", "熊猫大道", "交子大道"};
private String[] companys = {"京东", "腾讯", "百度", "小米", "米哈游", "网易", "字节跳动", "美团", "蚂蚁", "完美世界"};

随机获取person

    private Person getPerson() {Person person = Person.builder().name(names[random.nextInt(names.length)]).phone(18800000000L + random.nextInt(88888888)).salary(new BigDecimal(random.nextInt(99999))).company(companys[random.nextInt(companys.length)]).ifSingle(random.nextInt(2)).sex(random.nextInt(2)).address("四川省成都市" + addrs[random.nextInt(addrs.length)]).createUser(names[random.nextInt(names.length)]).build();return person;}

5、orm层用的mybatis

    <insert id="insertList" parameterType="com.example.demos.entity.Person">insert into person (name, phone, salary, company, if_single, sex, address, create_time, create_user)values<foreach collection="list" item="item" separator=",">(#{item.name}, #{item.phone}, #{item.salary}, #{item.company}, #{item.ifSingle}, #{item.sex},#{item.address}, now(), #{item.createUser})</foreach></insert>

准备工作完成,开始写核心逻辑

思路:
1、想要拉高插入效率,肯定不能够一条一条插了,必须得foreach批量插入,经测试,单次批量3w条以下时性价比最高,并且不用修改mysql配置
2、文章开头说了,得开多个线程异步插入,我们先把应用层效率拉满,mysql顶不顶得住
3、我们不可能单次提交一亿次insert,这谁顶得住,而且大量插入操作会很耗时,短时间内完不成,我们不可能一直守着,我的方案是用定时任务
。。。

算了屁话不多说,直接上demo

@Component
public class PersonService {private static final int THREAD_COUNT = 10;@Autowiredprivate PersonMapper personMapper;@Autowiredprivate ThreadPoolExecutor executor;private AtomicInteger integer = new AtomicInteger();private Random random = new Random();private String[] names = {"黄某人", "负债程序猿", "谭sir", "郭德纲", "蔡徐鸡", "蔡徐母鸡", "李狗蛋", "铁蛋", "赵铁柱"};private String[] addrs = {"二仙桥", "成华大道", "春熙路", "锦里", "宽窄巷子", "双子塔", "天府大道", "软件园", "熊猫大道", "交子大道"};private String[] companys = {"京东", "腾讯", "百度", "小米", "米哈游", "网易", "字节跳动", "美团", "蚂蚁", "完美世界"};@Scheduled(cron = "0/15 * * * * ?")public void insertList() {System.out.println("本轮任务开始,总任务数:" + THREAD_COUNT);long start = System.currentTimeMillis();AtomicLong end = new AtomicLong();for (int i = 0; i < THREAD_COUNT; i++) {Thread thread = new Thread(() -> {try {for (int j = 0; j < 20; j++) {personMapper.insertList(getPersonList(5000));}end.set(System.currentTimeMillis());System.out.println("本轮任务耗时:" + (end.get() - start) + "____已执行" + integer.addAndGet(1) + "个任务" + "____当前队列任务数" + executor.getQueue().size());} catch (Exception e) {e.printStackTrace();}});try {executor.execute(thread);} catch (Exception e) {System.out.println(e.getMessage());}}}private ArrayList<Person> getPersonList(int count) {ArrayList<Person> persons = new ArrayList<>(count);for (int i = 0; i < count; i++) {persons.add(getPerson());}return persons;}private Person getPerson() {Person person = Person.builder().name(names[random.nextInt(names.length)]).phone(18800000000L + random.nextInt(88888888)).salary(new BigDecimal(random.nextInt(99999))).company(companys[random.nextInt(companys.length)]).ifSingle(random.nextInt(2)).sex(random.nextInt(2)).address("四川省成都市" + addrs[random.nextInt(addrs.length)]).createUser(names[random.nextInt(names.length)]).build();return person;}
}

我的线程池配置,我电脑配置比较拉跨,只有12个线程…

@Configuration
public class ThreadPoolExecutorConfig {@Beanpublic ThreadPoolExecutor threadPoolExecutor() {ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 12, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));executor.allowCoreThreadTimeOut(true);return executor;}
}

测试

现在表是空的

项目跑起来

已经在开始插了,挂在后台让它自己跑吧。。。

25 minutes later ~

看下数据库

已经插入了1.04亿条数据,需求完成

第一条数据是15:54:15开始的,耗时大概25min

再来从数据库中看下一秒插入多少条,直接count某秒即可

一秒8.5w,嘎嘎快


来说下demo中核心的几个点:

  • 关于线程:我的cpu只有十二个线程,所以核心线程设置的10,留两个线程打杂;
  • 关于线程中的逻辑:每个线程有20次循环,每次循环插入5000条;
  • 关于获取随机对象:我没有统计创建对象的耗时,因为即使是创建100w个对象,但是这都是内存操作,跟insert这种io操作比起来,耗时几乎可以忽略,我就不测试了,你可以自己试试;
  • 关于效率:你们看到的版本(10 * 20 * 5000)是我只优化过几次的半成品,这种搭配最终的效率是100w条耗时12.5s,效率肯定不是最高的,但基本够用了;

可以看看之前的测试效率记录

10 * 100 * 1000:22-23s
10 * 50 * 2000:19-20s
10 * 10 * 10000 :18-20s

可以参考记录进行深度调优

哦对了,想效率更快的话,表不要建索引,insert时维护索引也是一笔不小的开销


完整demo给你们放在 码云
博主贼贴心,clone下来改下压妹儿jdbc就能跑,记得建表嗷~


ok我话说完

疯狂试探mysql单表insert极限:已实现每秒插入8.5w条数据相关推荐

  1. mysql单表狂 insert极限:已实现每秒插入2.5w条数据

    很多同学都有这样的困扰: 工作中项目的数据量不大,遇不到sql优化的场景:单表就几万,我优化个der啊: 业务对性能要求不高,远远没达到性能瓶颈:咱这项目又不是不能跑,优化个der啊: 确实,如果你的 ...

  2. mysql 插入秒_教你88秒插入1000万条数据到mysql数据库表,IG牛逼

    我用到的数据库为,mysql数据库5.7版本的首先自己准备好数据库表 其实我在插入1000万条数据的时候遇到了一些问题,现在先来解决他们,一开始我插入100万条数据时候报错,控制台的信息如下: com ...

  3. java mysql 快速插入1000w条数据_教你88秒插入1000万条数据到mysql数据库表

    我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入1000万条数据的时候遇到了一些问题,现在先来解决他们,一开始我插入100万条数据时候报错,控制台的信息如下: ...

  4. 教你急速快速批量插入1000万条数据到mysql数据库表面试题

    急速快速批量插入1000万条数据到mysql数据库表面试题 教你急速快速批量插入1000万条数据到mysql数据库表&面试题 我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好 ...

  5. Mysql 批量插入大量数据的两种方案以及优缺点(分别是 5W 条数据和 10W 条数据)

    Mysql 批量插入(5W 条数据和 10W 条数据) 1.批量插入思路 一般是有两种不同的思路: 1.for 循环批量插入 2.生成一条 SQL 语句,比如 insert into user(id, ...

  6. 运维高级学习(三):MySQL单表查询作业

    MySQL第三次作业 MySQL单表查询作业 素材如下: DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `cs_id` int(11) ...

  7. 关于mysql单表支持的最大大小

    mysql单表支持的最大存储空间大小为多少呢? 其实这个问题要拆分成两个问题. 第一是操作系统所采用的文件系统能支持的单个文件大小,比如: linux 2.2-intel 32-bit (ext2文件 ...

  8. MySQL单表膨胀优化之MyCat分库分表

    MySQL的单表达到多少量级时性能会下降?宽表在千万量级,窄表要好一点在1200W左右.但是MySQL单表达到1500W时性能开始急剧下降! 事实上MySQL单表可以存储10亿级数据,只是这时候性能比 ...

  9. mysql单表1000万条_mysql单表千万条数据测试

    软件环境:win7,mysql版本5.5,InnoDB存储引擎. 硬件环境:普通笔记本,CPU P8700双核2.53GHz,内存3G,5400转机械硬盘1000GB. 建了一张表,id列是自增长bi ...

最新文章

  1. linux shell显示下载进度,shell脚本测试下载速度
  2. 基于移动机器人的拣货系统研究进展
  3. Ecshop实现仿Taobao地区运费模板
  4. SQLserver 中时间减,并把结果转换成varchar类型,拼接上字符串
  5. mysql建表必须使用主键吗
  6. ajax中 get 和 post 的区别
  7. javascript中的运算符号
  8. Java中哪些操作会使线程释放锁资源
  9. PyTorch基础-softmax函数mnist数据集识别-03
  10. 20189222 《网络攻防实践》第二周作业
  11. 有些事,父母一定不能依着孩子!
  12. 使用vs自带的性能诊断工具
  13. DHTML【11】--DOM
  14. 纪广华老师:谈谈学习数论的参考书
  15. 色彩设计原理(里面有配色方案,也有配色网站)
  16. k8s 自定义dns_配置k8s dns
  17. ICEM CFD学习笔记(2)
  18. 易语言清理IEcookies 缓存等 可用于IE清理cookies
  19. 房东家的网线不用账号和密码就能上网怎么设置路由器
  20. 读书笔记5 《精进:如何成为一个很厉害的人》 采铜

热门文章

  1. 2019 南昌网络赛D FFT多个多项式相乘
  2. 计算机毕业论文附录的模板,论文附录格式-毕业论文附录的格式和写法
  3. 32 回归分析——一元线性回归模型
  4. arduino麦轮转弯程序_Arduino 自动避障智能小车制作教程
  5. 离散数学期末基础知识点复习
  6. 移动端前端抓包神器详解(whistle+weinre)
  7. 找工作笔试面试那些事儿(15)---互联网公司面试的零零种种和多家经验
  8. Composer入门教程 - 基本用法
  9. 1. java缓存-多级缓存概述
  10. ERP MES 两套系统源代码 WPF AGV C# WPF开发。 A,WPF MES 上位机产线执行系统