100万数据入mysql过程记录

个人瞎琢磨的,如有不对的地方还望个位看官给我指点一下,拜谢 

表:建表语句如下

CREATE TABLE `push_record_customer` (
  `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
  `push_task_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '推送任务id',
  `customer_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '学员id',
  `is_read` int DEFAULT '0' COMMENT '是否已读(0否1是)',
  `read_time` datetime DEFAULT NULL COMMENT '阅读时间',
  `push_status` int DEFAULT '0' COMMENT 'push推送状态(0-;1推送成功;2推送失败)',
  `push_fail_reason` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'push推送失败原因',
  `push_arrive_time` datetime DEFAULT NULL COMMENT 'push送达时间',
  `register_status` int DEFAULT NULL COMMENT '注册状态(1已注册2未注册)',
  `is_push_point` int DEFAULT NULL COMMENT '是否push点击(0否1是)',
  `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建日期',
  `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新日期',
  `tenant_id` int DEFAULT NULL COMMENT '商户编号',
  `deleted` int DEFAULT '0' COMMENT '逻辑删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='推送记录(学员)表'

 首先来讲,100万级的数据肯定是要使用多线程来插入的,(之前用过for循环+saveBatch()的方式插入100万条数据,直接插了一下午,好几个小时,肯定是不能采用这种方式的)

明确了要是用多线程,现在要知道的是mybatis的saveBatch方法 每次插入多少数据,相对来说效率是比较快的 我这里做了一些插入操作来对比

插入对比
插入数据量mybatis的saveBatch()插入在xml中手写sql插入
100017159ms1800ms
500088816ms2582ms
10000172845ms4090ms

查阅资料发现,批量操作的时候需要给jdbc链接叫一个参数rewriteBatchedStatements=true

MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。

MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。

只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL

另外这个选项对INSERT/UPDATE/DELETE都有效
 

 添加参数后重新测试一下:

插入数据量添加参数前(saveBatch())添加参数后(saveBatch())
100017159ms1850ms
500088816ms2261ms
10000172845ms2851ms

可以看出添加 rewriteBatchedStatements=true参数后saveBatch()方法与我们自己写的sql插入速率上差不多了.有了明显的提升

现在就是要找到每次插入多少条数据,相对来数,插入的时间最短,

插入数据量平均耗时(5次)ms平均每条耗时(ms)
1000(1807+1578+1622+1856+1576)/5=16881.688
2000(1995+1779+2260+1751+2113)/5=19800.994
3000(1832+2115+2046+1944+1960)/5=19800.66
4000(2206+2275+2036+2127+2624)/5=22540.563
5000(2225+2367+2296+2268+2215)/5=22740.455
6000(2459+2548+2347+2259+2347)/5=24100.402
7000(2347+2806+2480+2467+3166)/5=26530.379
8000(2511+3071+2799+2628+2713)/5=27440.343
9000(2828+3150+2875+3393+2904)/5=30300.337
10000(3046+3064+3299+2972+3101)/5=30960.309

这里数量可以加到10万每次,但是在多线程情况下一次插入操作 耗时比较长,可能会导致某些链接等不到cpu时间片而抛出超时关闭异常,所以我觉得还需要保证单次插入时间不能太长.还有就是cpu切换也是消耗资源的,数据库支持的最大连接数等都有影响.所以,线程最好不要开得太大.

我的电脑是i5的四核心的电脑 (每次重新测试我都会清空数据库数据,数据库数据越多后续插入越慢)

测试插入数据数量每次插入数量线程数线程池核心数时间(s)
100000050002040188
1000000100002040189
1000000200002040206
1000000300002040202
10000001000001040211
100000050005050190
1000000100005050192
10000005000100100193
100000010000100100154

100个线程,每次插入10000调数据的时候 出现了链接超时的异常,可以看到我设置的数据库连接池超时时间为100秒(已经很长了),应该是线程太多了,而且每一个线程插入10000调数据的时间太长,导致一部分线程一直拿不到cpu时间片,最终导致了链接超时. 所以线程不是越多越好,每次插入的数据也不是越多越好.

测试过程中还发现一个蛋疼的问题,我本地数据库效率极其低,一个select count(*) 100万居然要一分多钟 ,于是我买了个腾讯云服务器,在服务器上按照默认的配置安装了mysql来进行测试.才算正常了 select count(*)100万到0.3s左右 

结论:插入100万条数据

1.批量操作数据要在jdbc链接添加参数rewriteBatchedStatements=true

2 .每次插入的数据最好不要超过10000/次 

3.开启的线程最好不要超过50(4核心,更多核心的没试过)

4.数据库链接超时的时间修改长一点.(默认是30s) 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值