使用golang插入mysql性能提升经验

时间:2022-01-15 08:27:43

前言

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性能提升经验的更多相关文章

  1. Mysql学习总结(38)——21条MySql性能优化经验

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情. 当我们去设计数据库表结构,对操作数 ...

  2. MySQL性能优化经验

    核心 不做运算 md5() Order By Rand() 控制单表数据量 保持表字段苗条 平衡范式与冗余 拒绝3B Big SQL Big Transaction Big Batch 字段 用好数值 ...

  3. 10个提升MySQL性能的小技巧

    从工作量分析到索引的三条规则,这些专家见解肯定会让您的MySQL服务器尖叫. 在所有的关系数据库中,MySQL已经被证明了完全是一头野兽,只要通知停止运行就绝对不会让你多等一秒钟,使你的应用置于困境之 ...

  4. paip&period;提升性能---mysql 性能 测试以及 参数调整&period;txt

    paip.提升性能---mysql 性能 测试以及 参数调整.txt 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://b ...

  5. MySQL 8&period;0 —— CATS事务调度算法的性能提升

    原文地址:https://mysqlserverteam.com/contention-aware-transaction-scheduling-arriving-in-innodb-to-boost ...

  6. MYSQL性能优化的最佳20&plus;条经验

    MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论  131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...

  7. 【转】MySQL批量SQL插入各种性能优化

    原文:http://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=403182899&idx=1&sn=74edf28b0bd29 ...

  8. 二十种实战调优MySQL性能优化的经验

    二十种实战调优MySQL性能优化的经验 发布时间:2012 年 2 月 15 日 发布者: OurMySQL 来源:web大本营   才被阅读:3,354 次    消灭0评论     本文将为大家介 ...

  9. 使用ThinkPHP开发中MySQL性能优化的最佳21条经验

    使用ThinkPHP开发中MySQL性能优化的最佳21条经验讲解,目前,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更 ...

随机推荐

  1. SqlCommand执行带GO的SQL脚本文件

    今天工作中遇到了这个问题,其实只要把GO替换成“;”就行了,其它人写的例子用Split来拆分这一个脚本文件的内容,完全没有必要.希望对你有用.

  2. debian vi

    这次用DigitalOcean VPS发现vi的方向键变成字母,没办法正常使用,搜索了下找到了解决办法. 1 vi /etc/vim/vimrc.tiny 找到set compatible改为set ...

  3. Linux更改默认jdk

    RHEL默认安装Open JDK--java-1.6.0-openjdk-1.6.0.0-1.66.1.13.0.el6.x86_64,现在要换成Oracle JDK1.7.0_51 1. (可选)删 ...

  4. Javascript闭包的一些研究

    原文:Javascript闭包的一些研究 本文不谈闭包的概念,因为概念容易把人搞晕,本文希望通过几个鲜活的例子来探究闭包的性质,相信对理解闭包会有所帮助. 程序1 var f = (function( ...

  5. 我喜欢的两个js类实现方式

    闭包实现 变量是不会变的:) var myApplication = function(){ var name = 'Yuri'; var age = '34'; var status = 'sing ...

  6. SharePoint 2013 配置InfoPath 列表表单

    转载来源:http://www.cnblogs.com/jianyus/p/3470113.html SharePoint列表,都是通过表单展示,有时候不太符合要求,这时候,我们可以通过定制表单,来是 ...

  7. Dockerfile注意事项

    准则 尽量将Dockerfile放在空目录中,如果目录中必须有其他文件,则使用.dockerignore文件. 避免安装不必须的包. 每个容器应该只关注一个功能点. 最小化镜像的层数. 多行参数时应该 ...

  8. 忘记Jenkins管理员密码的解决办法

    一.admin密码未更改情况 1.进入\Jenkins\secrets目录,打开initialAdminPassword文件,复制密码: 2.访问Jenkins页面,输入管理员admin,及刚才的密码 ...

  9. 浅谈static其一之不死变量

    在学习汇编的过程中,小有所悟,遂把自己所思所想记下,以便日后查阅. 首先说说我对这个关键字的理解.static字面上就是静止的.静态的.不变的之类的意思,所以在被它修饰之后,应该也会带有这样的一些特点 ...

  10. redis 五大数据类型之string篇

    一: 1:string(字符串) string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value. string类型是二进制安全的.意思是redis ...