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 相关文章推荐
如何使用Maxwell实时同步mysql数据
Apr 08 MySQL
详解MySQL事务的隔离级别与MVCC
Apr 22 MySQL
MySQL 逻辑备份与恢复测试的相关总结
May 14 MySQL
MySQL 存储过程的优缺点分析
May 20 MySQL
mysql 带多个条件的查询方式
Jun 05 MySQL
MySQL空间数据存储及函数
Sep 25 MySQL
mysql 联合索引生效的条件及索引失效的条件
Nov 20 MySQL
MySQL磁盘碎片整理实例演示
Apr 03 MySQL
CentOS MySql8 远程连接实战
Apr 19 MySQL
mysql中如何用命令创建联合唯一索引
Apr 20 MySQL
MySQL数据库配置信息查看与修改方法详解
Jun 25 MySQL
SQL中去除重复数据的几种方法汇总(窗口函数对数据去重)
May 08 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中4种常用的抓取网络数据方法
2015/06/04 PHP
PHP获取中国时间(上海时区时间)及美国时间的方法
2017/02/23 PHP
Yii2框架中使用PHPExcel导出Excel文件的示例
2017/08/09 PHP
PHP实现文件上传与下载
2020/08/28 PHP
Locate a File Using a File Open Dialog Box
2007/06/18 Javascript
用Javascript评估用户输入密码的强度实现代码
2011/11/30 Javascript
jquery入门必备的基本认识及实例(整理)
2013/06/24 Javascript
jquery动态调整div大小使其宽度始终为浏览器宽度
2014/06/06 Javascript
jquery.cookie.js用法实例详解
2015/12/25 Javascript
Javascript基础_简单比较undefined和null 值
2016/06/14 Javascript
HTML5 JS压缩图片并获取图片BASE64编码上传
2020/11/16 Javascript
js编写的treeview使用方法
2016/11/11 Javascript
详解jQuery选择器
2016/12/21 Javascript
vue组件实例解析
2017/01/10 Javascript
原生JS与jQuery编写简单选项卡
2017/10/30 jQuery
总结JavaScript在IE9之前版本中内存泄露问题
2018/04/28 Javascript
使用D3.js+Vue实现一个简单的柱形图
2018/08/05 Javascript
jQuery实现图片切换效果
2020/10/19 jQuery
vue使用exif获取图片旋转,压缩的示例代码
2020/12/11 Vue.js
[01:13]这,就是刀塔
2014/07/16 DOTA
Python3.2中的字符串函数学习总结
2015/04/23 Python
Python实现队列的方法
2015/05/26 Python
Python的Django框架中消息通知的计数器实现教程
2016/06/13 Python
基于DataFrame筛选数据与loc的用法详解
2018/05/18 Python
python使用插值法画出平滑曲线
2018/12/15 Python
Python实现简易过滤删除数字的方法小结
2019/01/09 Python
python使用wxpy实现微信消息防撤回脚本
2019/04/29 Python
新加坡领先的在线生活方式和杂货购物网站:EAMART
2019/04/02 全球购物
Bonami斯洛伐克:购买家具和家居饰品
2019/07/02 全球购物
英国婚礼商城:Wedding Mall
2019/11/02 全球购物
SIDESTEP荷兰:在线购买鞋子
2019/11/18 全球购物
ParcelABC西班牙:包裹运送和快递服务
2019/12/24 全球购物
英国领先的独立酒精饮料零售商:DrinkSupermarket
2021/01/13 全球购物
JavaScript实现前端网页版倒计时
2021/03/24 Javascript
vue backtop组件的实现完整代码
2021/04/07 Vue.js
详解MySQL的内连接和外连接
2023/05/08 MySQL