使用golang插入mysql性能提升经验
前言
golang可以轻易制造高并发,在某些场景很合适,比如爬虫的时候可以爬的更加高效。但是对应某些场景,如文件读写,数据库访问等IO为瓶颈的场合,就没有什么优势了。
前提基础
1、golang数据库访问
在golang中数据库访问使用”database/sql”包提供的接口,不同的数据库,比如pg、mysql只需要提供对应的驱动就可以了。注意”database/sql”包提供的接口只针对关系型数据库,nosql如redis和mongodb都是直接使用对应的客户端包,不实现”database/sql”包提供的接口。关于”database/sql”包,这里不做讲述,后续在基础回顾上巩固下。总体上就是提供了连接、事务处理、还有就是打开的时候注意打开的时候并没有连接,而是产生一个池,每次有交互的时候才产生一个连接(事务交互除外)。
2、数据库插入优化基础
1)插入无索引表会比插入有索引的表快,毕竟建立索引总是要增加一些额外操作
2)插入小表比插入大表快,业务一般插入速度是以条数计算,大表一条记录比较大,需要IO的时间比较长。
3)多个连接一起插入会比单连接快,因为mysql不是单线程。
4)日志缓存增大可以加快插入速度,因为减少了IO访问次数。
5)一次插入多条数据可以加快插入速度。
实践经验
ps:以小表做实验,都用一个环境,比较差异。
表结构:
create table lamp(
id bigint not null primary key,
state char(1),
collecttime timestamp);
1、无任何优化,一条条插入,且使用同一个链接
代码片段:
fmt.Println(time.Now().Unix())
_, err = db.Prepare("INSERT INTO lamp (id, state, collecttime)VALUES(?,'0', '20180103002930')")
if err != nil {
fmt.Println(err)
return
}
for i := 0; i < 100000; i++ {
_, err := db.Exec(execstring + data)
if err != nil {
fmt.Println(err)
return
}
}
fmt.Println(time.Now().Unix())
结果:
1514911765
1514912248
使用了483s 平均100000/500 大概是200次每秒。
2、单连接,使用事务。
fmt.Println(time.Now().Unix())
insert, err = db.Prepare("INSERT INTO lamp (id, state, collecttime)VALUES(?,'0', '20180103002930')")
if err != nil {
fmt.Println(err)
return
}
begin, err := db.Begin()
if err != nil {
fmt.Println(err)
return
}
for i := 0; i < 100000; i++ {
_, err := begin.Stmt(insert).Exec(i)
if err != nil {
fmt.Println(err)
return
}
}
err = begin.Commit()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(time.Now().Unix())
运行结果
1514910923
1514911049
使用了129s 平均100000/125, 约为800次每秒
3、批量插入,每1W条执行一次插入操作。,注意max_allowed_packet要设置的足够大
fmt.Println(time.Now().Unix())
for i := 0; i < 1000; i++ {
for j := i * 10000; j < i*10000+10000; j++ {
if j < i*10000+9999 {
id := strconv.Itoa(j)
onedata := "(" + id + ", '0', '20180103002930'), "
data = data + onedata
} else {
id := strconv.Itoa(j)
onedata := "(" + id + ",'0', '20180103002930')"
data = data + onedata
}
}
_, err := db.Exec(execstring + data)
if err != nil {
fmt.Println(err)
return
}
}
fmt.Println(time.Now().Unix())
结果:
1514969811
1514970318
使用了507s 平均10000000/500, 约为2W次每秒
4、并发插入,使用100个协程插入
fmt.Println(time.Now().Unix())
intertnumber := 0
for i := 0; i < 10; i++ {
value := i
go func() {
execstring := "INSERT INTO lamp (id, state, collecttime)VALUES"
for k := value; k < 1000; k = k + 10 {
data := " "
for j := k * 10000; j < k*10000+10000; j++ {
if j < k*10000+9999 {
id := strconv.Itoa(j)
onedata := "(" + id + ", '0', '20180103002930'), "
data = data + onedata
} else {
id := strconv.Itoa(j)
onedata := "(" + id + ",'0', '20180103002930')"
data = data + onedata
} }
//fmt.Println(execstring + data)
_, err := db.Exec(execstring + data)
if err != nil {
fmt.Println(err)
return
}
intertnumber = intertnumber + 10000
}
}()
}
for intertnumber < 9999999 {
time.Sleep(1 * time.Second)
}
fmt.Println(time.Now().Unix())
运行结果:
1514974432
1514974796
使用了363s 平均10000000/500, 约为2.7W次每秒
4、1千W条数据,开1000个协程做插入操作,每次插入1W条数据。mysql最大连接数设置为2048
运行结果:
mysql宕机,CPU,MEM使用过高,IO使用并不高。
总结:
从程序层面上看:
1、使用事务会比较快一些。
2、多连接插入会快很多,当读写成为瓶颈的时候,效果就不太明显。
3、一次插入多条数据也会快很多。
4、高并发大量插入请求,mysql服务的应对措施是宕机,而不是拒绝请求。(这个跟笔者代码也有一定关系,因为100个协程前面都是再抢CPU构造插入请求,几乎都是同时向mysql请求),mysql在高并发场景,如果承受不住会宕机,这点在设计上需要注意。
原文:http://blog.csdn.net/m0_38132420/article/details/78964433
使用golang插入mysql性能提升经验的更多相关文章
- Mysql学习总结(38)——21条MySql性能优化经验
今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情. 当我们去设计数据库表结构,对操作数 ...
- MySQL性能优化经验
核心 不做运算 md5() Order By Rand() 控制单表数据量 保持表字段苗条 平衡范式与冗余 拒绝3B Big SQL Big Transaction Big Batch 字段 用好数值 ...
- 10个提升MySQL性能的小技巧
从工作量分析到索引的三条规则,这些专家见解肯定会让您的MySQL服务器尖叫. 在所有的关系数据库中,MySQL已经被证明了完全是一头野兽,只要通知停止运行就绝对不会让你多等一秒钟,使你的应用置于困境之 ...
- paip.提升性能---mysql 性能 测试以及 参数调整.txt
paip.提升性能---mysql 性能 测试以及 参数调整.txt 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://b ...
- MySQL 8.0 —— CATS事务调度算法的性能提升
原文地址:https://mysqlserverteam.com/contention-aware-transaction-scheduling-arriving-in-innodb-to-boost ...
- MYSQL性能优化的最佳20+条经验
MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论 131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...
- 【转】MySQL批量SQL插入各种性能优化
原文:http://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=403182899&idx=1&sn=74edf28b0bd29 ...
- 二十种实战调优MySQL性能优化的经验
二十种实战调优MySQL性能优化的经验 发布时间:2012 年 2 月 15 日 发布者: OurMySQL 来源:web大本营 才被阅读:3,354 次 消灭0评论 本文将为大家介 ...
- 使用ThinkPHP开发中MySQL性能优化的最佳21条经验
使用ThinkPHP开发中MySQL性能优化的最佳21条经验讲解,目前,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更 ...
随机推荐
- 牛客小白月赛 G 异或 找规律
链接:https://www.nowcoder.com/acm/contest/135/G来源:牛客网 题目描述 从前,Apojacsleam家的水族箱里,养了一群热带鱼. 在这几条热带鱼里,Apoj ...
- 剑指offer】Java版代码(完整版)
转自:剑指offer]Java版代码(完整版) 转自:[剑指offer] JAVA版题解(完整版)
- java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口
函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...
- Android四大组件初识之Activity
一.Activity的生命周期 Activity生命周期是一系列方法调用.熟悉各个方法调用时间,我们在创建activity就能根据具体实现选择合适的方法覆盖. 1. 覆盖Activity的生命周期方 ...
- JAVA集合框架包含的内容
Java集合框架提供了一套性能优良.使用方便的接口和类,他们位于java.util包中. Collection接口 主要有List.Set等实现类,Map接口主要有HashMap.TreeMap等实现 ...
- LeetCode第七题
Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 Have you ...
- 在命令行已经pip install flask-script,但是导包时出错
问题:(已经安装好了flask-script,但是导入不成功) 然后在代码中导入相应的包:(报红) 后来发现是在自己创建项目的时候勾选的是创建的是在虚拟环境下的项目,所以环境有问题 所以我应该在虚拟环 ...
- 用button 属性来保存字符串地址
我用到for循环创建button 通过点击不同的按钮拿到每个button对应的链接地址,因为button的个数也是通过后台数据返回.上代码: //保存到数组 _array = [Article mj ...
- ActiveMQ的安装与使用。
1.什么是ActiveMQ ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE .4规范的 JMS Provider实现,尽 ...
- 松软科技课堂:SQL-SELECT-INTO语句
SQL SELECT INTO 语句可用于创建表的备份复件. SELECT INTO 语句 SELECT INTO 语句从一个表中选取数据,然后把数据插入另一个表中. SELECT INTO 语句常用 ...