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 相关文章推荐
jdbc使用PreparedStatement批量插入数据的方法
Apr 27 MySQL
mysql 8.0.24 安装配置方法图文教程
May 12 MySQL
探究Mysql模糊查询是否区分大小写
Jun 11 MySQL
MySQL中日期型单行函数代码详解
Jun 21 MySQL
MySQL系列之一 MariaDB-server安装
Jul 02 MySQL
mysql如何能有效防止删库跑路
Oct 05 MySQL
MySQL Innodb索引机制详细介绍
Nov 23 MySQL
MySQL图形化管理工具Navicat安装步骤
Dec 04 MySQL
mysql分组后合并显示一个字段的多条数据方式
Jan 22 MySQL
Pycharm远程调试和MySQL数据库授权问题
Mar 18 MySQL
详细介绍MySQL中limit和offset的用法
May 06 MySQL
MySQL索引失效十种场景与优化方案
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
CodeIgniter框架过滤HTML危险代码
2014/06/12 PHP
Laravel框架模型的创建及模型对数据操作示例
2019/05/07 PHP
PHP超级全局变量【$GLOBALS,$_SERVER,$_REQUEST等】用法实例分析
2019/12/11 PHP
php与阿里云短信接口接入操作案例分析
2020/05/27 PHP
prototype Element学习笔记(篇二)
2008/10/26 Javascript
Jquery Uploadify上传带进度条的简单实例
2014/02/12 Javascript
jQuery的$.proxy()应用示例介绍
2014/04/03 Javascript
jQuery中die()方法用法实例
2015/01/19 Javascript
jquery css实现邮箱自动补全
2016/11/14 Javascript
Angular4实现图片上传预览路径不安全的问题解决
2017/12/25 Javascript
vue实现文件上传功能
2018/08/13 Javascript
基于javascript的拖拽类封装详解
2019/04/19 Javascript
解决vue里a标签值解析变量,跳转页面,前面加默认域名端口的问题
2020/07/22 Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
2020/08/14 Javascript
element-plus一个vue3.xUI框架(element-ui的3.x 版初体验)
2020/12/02 Vue.js
Python编程之微信推送模板消息功能示例
2017/08/21 Python
python re模块findall()函数实例解析
2018/01/19 Python
python 实现在Excel末尾增加新行
2018/05/02 Python
详解python异步编程之asyncio(百万并发)
2018/07/07 Python
选择Python写网络爬虫的优势和理由
2019/07/07 Python
Python Django 前后端分离 API的方法
2019/08/28 Python
Nike德国官网:Nike.com (DE)
2018/11/13 全球购物
日本最佳原创设计品牌:Felissimo(芬理希梦)
2019/03/19 全球购物
Linux Interview Questions For software testers
2012/06/02 面试题
护理专科毕业推荐信
2013/11/10 职场文书
教育实习生的自我评价分享
2013/11/21 职场文书
大众服装店创业计划书范文
2014/01/01 职场文书
大学信息公开实施方案
2014/03/09 职场文书
2014学习全国两会精神心得体会2000字
2014/03/11 职场文书
我们的节日元宵活动方案
2014/08/23 职场文书
超市采购员岗位职责
2015/04/07 职场文书
趣味运动会通讯稿
2015/07/18 职场文书
校园运动会广播稿
2015/08/19 职场文书
python实现过滤敏感词
2021/05/08 Python
如何基于python实现单目三维重建详解
2022/06/25 Python
Redis+AOP+自定义注解实现限流
2022/06/28 Redis