mysql 数据插入优化方法之concurrent_insert


Posted in MySQL onJuly 01, 2021

当一个线程对一个表执行一个DELAYED语句时,如果不存在这样的处理程序,一个处理器线程被创建以处理对于该表的所有DELAYED语句。

通常来说,在MyISAM里读写操作是串行的,但当对同一个表进行查询和插入操作时,为了降低锁竞争的频率,根据concurrent_insert的设置,MyISAM是可以并行处理查询和插入的:

当concurrent_insert=0时,不允许并发插入功能。
当concurrent_insert=1时,允许对没有洞洞的表使用并发插入,新数据位于数据文件结尾(缺省)。
当concurrent_insert=2时,不管表有没有洞洞,都允许在数据文件结尾并发插入。

这样看来,把concurrent_insert设置为2是很划算的,至于由此产生的文件碎片,可以定期使用OPTIMIZE TABLE语法优化。

max_write_lock_count:

缺省情况下,写操作的优先级要高于读操作的优先级,即便是先发送的读请求,后发送的写请求,此时也会优先处理写请求,然后再处理读请求。这就造成一 个问题:一旦我发出若干个写请求,就会堵塞所有的读请求,直到写请求全都处理完,才有机会处理读请求。此时可以考虑使用 max_write_lock_count:

max_write_lock_count=1

有了这样的设置,当系统处理一个写操作后,就会暂停写操作,给读操作执行的机会。

low-priority-updates:

我们还可以更干脆点,直接降低写操作的优先级,给读操作更高的优先级。

low-priority-updates=1

综合来看,concurrent_insert=2是绝对推荐的,至于max_write_lock_count=1和low-priority- updates=1,则视情况而定,如果可以降低写操作的优先级,则使用low-priority-updates=1,否则使用 max_write_lock_count=1。

set-variable = max_allowed_packet=1M
set-variable = net_buffer_length=2K

在myisam engine下

1. 尽量使用insert into table_name values (…), (…..),(…..)这样形式插入数据,避免使用inset into table_name values (); inset into table_name values (); inset into table_name values ();

2 增加bulk_insert_buffer_size(默认8M)

3 如果是非空表,使用alter table table_name disable keys,然后load data infile,导入完数据在执行:

alter table table_name enable keys. 如果是空表,就不需要这个操作,因为myisam表在空表中导入数据时,是先导入数据然后建立indexs。

4 在插入数据时考虑使用:insert delayed….这样操作实际mysql把insert操作放到队列里面,进行相对集中的插入,速度更快。

5. 使用load data infile 比使用insert 操作快近20倍,尽量使用此操作。

在innodb engine下

1.导入数据之前执行set unique_checks=0来禁止对唯一索引的检查,数据导入完成之后再运行set unique_checks=1.

2. 导入数据之前执行set foreign_key_checks=0来禁止对外键的检查,数据导入完成之后再执行set foreign_key_checks=1.

3.导入数据之前执行set autocommit=0禁止自动事务的自动提交,数据导入完成之后,执行set autocommit=1 恢复自动提交操作。

使用innodb engine的表,物理存储都是按PK的顺序存的。不能使用类似于myisam一样disable keys.

硬件上提高磁盘的I/0对插入速度很有好处(所以如果进行大数据量的导入导出工作,尽量在比较NB的硬件上进行,能缩减完成的时间,已经防止出现问题)。

当一个线程对一个表执行一个DELAYED语句时,如果不存在这样的处理程序,一个处理器线程被创建以处理对于该表的所有DELAYED语句。

线程检查处理程序是否已经获得了一个DELAYED锁;如果没有,它告诉处理程序去获得。即使其他的线程有在表上的一个READ或WRITE锁,也能获得 DELAYED锁。然而,处理程序将等待所有ALTER TABLE锁或FLUSH TABLES以保证表结构是最新的。

线程执行INSERT语句,但不是将行写入表,它把最后一行的副本放进被处理器线程管理的一个队列。任何语法错误都能被线程发觉并报告给客户程序。

顾客不能报告结果行的重复次数或AUTO_INCREMENT值;它不能从服务器获得它们,因为INSERT在插入操作完成前返回。如果你使用C API,同样原因,mysql_info()函数不返回任何有意义的东西。

当行被插入到表中时,更新日志有处理器线程更新。在多行插入的情况下,当第一行被插入时,更新日志被更新。
在每写入delayed_insert_limit行后,处理器检查是否任何SELECT语句仍然是未完成,如果这样,在继续之前允许执行这些语句。

当处理器在它的队列中没有更多行时,表被解锁。如果在delayed_insert_timeout秒内没有收到新的INSERT DELAYED命令,处理器终止。

如果已经有多于delayed_queue_size行在一个特定的处理器队列中未解决,线程等待直到队列有空间。这有助于保证mysqld服务器对延迟的内存队列不使用所有内存。

处理器线程将在Command列的MySQL进程表中显示delayed_insert。如果你执行一个FLUSH TABLES命令或以KILL thread_id杀死它,它将被杀死,然而,它在退出前首先将所有排队的行存进表中。在这期间,这次它将不从其他线程接受任何新的INSERT命令。如 果你在它之后执行一个INSERT DELAYED,将创建一个新的处理器线程。

注意,上述意味着,如果有一个INSERT DELAYED处理器已经运行,INSERT DELAYED命令有比正常INSERT更高的优先级!其他更新命令将必须等到INSERT DELAY排队变空、杀死处理器线程(用KILL thread_id)或执行FLUSH TABLES。

下列状态变量提供了关于INSERT DELAYED命令的信息: Delayed_insert_threads 处理器线程数量

Delayed_writes 用INSERT DELAYED被写入的行的数量
Not_flushed_delayed_rows 等待被写入的行数字

高并发insert语句的解决方法

前言

1、防止数据多次修改

1.1 、insert方案

1、添加uniqpue进行解决(重复则是更新)

insert一般没什么问题,直接控制好unique就可以,这样的话,就不会插入两条(如果重复了则,进行更新操作)

2、update方案

1、redis分布式锁、消息队列(每次只插入一个)

2、mysql锁(更新可以使用乐观锁)

2、高并发下的安全性

1、在线的网站上去执行一个大的DELETE或INSERT查询,要避免你的操作让你的整个网站停止相应。因为这两个操作是会锁表的(update也是,如果没有指定唯一主键或者索引的话,会锁表),表一锁住了,别的操作都进不来了。所以一定要非常小心

2、如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让你泊WEB服务Crash,还可能会让你的整台服务器马上?炝恕 >

2.1、解决方案

2.1.1、表的调整

把表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。(如果有一百多个字段是很恐怖的)

示例一:

在Users表中有一个字段是家庭地址,这个字段是可选字段,相比起,而且你在数据库操作的时候除了个人信息外,你并不需要经常读取或是改写这个字段。那么,为什么不把他放到另外一张表中呢?这样会让你的表有更好的性能,大家想想是不是,大量的时候,我对于用户表来说,只有用户ID,用户名,口令,用户角色等会被经常使用。小一点的表总是会有好的性能。

示例二:

你有一个叫“last_login”的字段,它会在每次用户登录时被更新。但是,每次更新时会导致该表的查询缓存被清空。所以,你可以把这个字段放到另一个表中,这样就不会影响你对用户ID,用户名,用户角色的不停地读取了,因为查询缓存会帮你增加很多性能。hp程序员之家

另外,需要注意的是,这些被分出去的字段所形成的表,我们是认为不会经常是join的,否则,这样的性能会比不分割表的时候时还要差,而且,会是极数级的下降

MySQL 相关文章推荐
浅析InnoDB索引结构
Apr 05 MySQL
MySQL表的增删改查(基础)
Apr 05 MySQL
详解GaussDB for MySQL性能优化
May 18 MySQL
Mysql Online DDL的使用详解
May 20 MySQL
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
Jun 26 MySQL
MySQL索引是啥?不懂就问
Jul 21 MySQL
详细聊聊关于Mysql联合查询的那些事儿
Oct 24 MySQL
MySQL基于索引的压力测试的实现
Nov 07 MySQL
Mysql多层子查询示例代码(收藏夹案例)
Mar 31 MySQL
mysql中如何用命令创建联合唯一索引
Apr 20 MySQL
Mysql表数据比较大情况下修改添加字段的方法实例
Jun 28 MySQL
MySQL常用慢查询分析工具详解
Aug 14 MySQL
MySQL的Query Cache图文详解
MySQL高速缓存启动方法及参数详解(query_cache_size)
Jul 01 #MySQL
mysql优化之query_cache_limit参数说明
Jul 01 #MySQL
MySQL中存储时间的最佳实践指南
Jul 01 #MySQL
MySQL连表查询分组去重的实现示例
Jul 01 #MySQL
python中的mysql数据库LIKE操作符详解
Jul 01 #MySQL
解决Mysql的left join无效及使用的注意事项说明
You might like
php权重计算方法代码分享
2014/01/09 PHP
PHP中nowdoc和heredoc使用需要注意的一点
2014/03/21 PHP
php使用数组填充下拉列表框的方法
2015/03/31 PHP
php冒泡排序与快速排序实例详解
2015/12/07 PHP
Zend Framework教程之Zend_Controller_Plugin插件用法详解
2016/03/07 PHP
php实现的中秋博饼游戏之绘制骰子图案功能示例
2017/11/06 PHP
目前流行的JavaScript库的介绍及对比
2013/09/29 Javascript
JavaScript实现点击自动选择TextArea文本的方法
2015/07/02 Javascript
jquery+php随机生成红包金额数量代码分享
2015/08/27 Javascript
跟我学习javascript的循环
2015/11/18 Javascript
深入学习jQuery Validate表单验证(二)
2016/01/18 Javascript
AngularJS中的指令全面解析(必看)
2016/05/20 Javascript
基于CSS3和jQuery实现跟随鼠标方位的Hover特效
2016/07/25 Javascript
使用jQuery,Angular实现登录界面验证码详解
2017/04/27 jQuery
Javascript刷新页面的实例
2017/09/23 Javascript
JS非行间样式获取函数的实例代码
2018/06/05 Javascript
详解Angular Karma测试的持续集成实践
2019/11/15 Javascript
JavaScript使用百度ECharts插件绘制饼图操作示例
2019/11/26 Javascript
[01:11:27]2018DOTA2亚洲邀请赛小组赛 A组加赛 Newbee vs Optic
2018/04/03 DOTA
Python使用htpasswd实现基本认证授权的例子
2014/06/10 Python
零基础写python爬虫之抓取百度贴吧代码分享
2014/11/06 Python
python实现清屏的方法
2015/04/30 Python
python2.7使用plotly绘制本地散点图和折线图
2019/04/02 Python
Python字典的概念及常见应用实例详解
2019/10/30 Python
浅谈Python中range与Numpy中arange的比较
2020/03/11 Python
方太官方网上商城:销售方太抽油烟机、燃气灶、消毒柜等
2017/01/17 全球购物
加拿大领先的优质厨具产品在线购物网站:Golda’s Kitchen
2017/11/17 全球购物
TIME时代杂志台湾总代理:台时亚洲
2018/10/22 全球购物
澳大利亚排名第一的露营和户外设备在线零售商:Outbax
2020/05/06 全球购物
初中美术教学反思
2014/01/29 职场文书
绿色城市实施方案
2014/03/19 职场文书
解放思想大讨论活动心得体会
2014/09/11 职场文书
财政专业大学生职业生涯规划书
2014/09/17 职场文书
团队会宣传标语
2014/10/09 职场文书
Pytest之测试命名规则的使用
2021/04/16 Python
python神经网络学习 使用Keras进行简单分类
2022/05/04 Python