通常情况下,当访问某张表的时候,读取者首先必须获取该表的锁,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取者完成操作)。当读取者完成对表的操作的时候,锁就会被解除。如果写入者正在等待的时候,另一个读取操作到达了,该读取操作也会被阻塞(block),因为默认的调度策略是写入者优先于读取者。当第一个读取者完成操作并解放锁后,写入者开始操作,并且直到该写入者完成操作,第二个读取者才开始操作。

通过LOCK TABLES和UNLOCK TABLES语句可以显式地获取或释放锁,但是在通常情况下,服务器的锁管理器会自动地在需要的时候获取锁,在不再需要的时候释放锁。获取的锁的类型依赖于客户端是写入还是读取操作。

对某张表进行写入操作的客户端必须拥有独占的(排他的)访问权的锁。操作在进行的过程中,该数据表处于不一致的(inconsistent)状态,因为数据记录在删除、添加或修改的时候,数据表上的索引也可能需要更新以相互匹配。允许两个客户端同时写入一张数据表是不利的,因为这样的操作会很快使数据表中的信息成为一堆无用的垃圾。同时允许客户端读取变化之中的数据表也不正确,因为正在读取的位置中的数据可能正在变化(修改),读取的结果可能并不是真实的。因此对某张表执行读取操作的客户端也必须获取一个锁,防止在读取的过程中,其它的客户端写入或改变表。但是这个锁不需要独占的访问权。因为读取操作不会改变数据,因此没有理由让某个读取者阻止其它的读取者访问这张表。故读取锁可允许其它的客户端在同一时刻读取这张表。

虽然通过锁机制,可以实现多线程同时对某个表进行操作,但当某个线程作更新操作时,首先要获得独占的访问权。在更新的过程中,所有其它想要访问这个表的线程必须要等到其更新完成为止。此时就会导致锁竞争的问题,从而导致用户等待时间的延长。
要提高MySQL的更新/插入效率,应首先考虑降低锁的竞争,减少写操作的等待时间。

1.同时插入多行记录时,宜使用多个值表的INSERT 语句

如果可以同时从同一客户插入很多行时,宜使用多个值表的INSERT 语句。多个值表的 INSERT 语句 ,可以大大缩减客户端与数据库之间的连接、语法分析等消耗,使得效率比分开执行的单个 INSERT 语句快很多。
如批量插入:
INSERT INTO tb (fa, fb, fc) VALUES ('1', '12', '13'), ('2', '22', '23'), ('3', '32', '33'),
多值的 INSERT语句还可以通过调整 bulk_insert_buffer_size 参数来提高数据插入的效率,这个参数设置的是 bulk insert 的缓存大小,默认是 8M 。注意,这只能对myisam表使用。
3)可以对myisam表并行插入Concurrent_insert系统变量可以被设置用于修改concurrent-insert处理。该变量默认设置为1。如果concurrent_insert被设置为0,并行插入就被禁用。如果该变量被设置为2,在表的末端可以并行插入,即便该表的某些行已经被删除。

2.考虑使用replace 语句代替insert语句

根据应用情况可以使用replace 语句代替insert/update语句。例如:如果一个表在一个字段上建立了唯一索引,当向这个表中使用已经存在的键值插入一条记录,将会抛出一个主键冲突的错误。如果我们想用新记录的值来覆盖原来的记录值时,就可以使用REPLACE语句。

使用REPLACE插入记录时,如果记录不重复(或往表里插新记录),REPLACE功能与INSERT一样,如果存在重复记录,REPLACE就使用新记录的值来替换原来的记录值。使用REPLACE的最大好处就是可以将DELETE和INSERT合二为一,形成一个原子操作。这样就可以不必考虑同时使用DELETE和INSERT时添加事务等复杂操作了。

在使用REPLACE时,表中必须有唯一有一个PRIMARY KEY或UNIQUE索引,否则,使用一个REPLACE语句没有意义。

mysql replace语句:

用法1:replace into:

replace into table (id,name) values('1','aa'),('2','bb')

此语句的作用是向表table中插入两条记录。如果主键id为1或2不存在就相当于插入语句:

insert into table (id,name) values('1','aa'),('2','bb')

如果存在相同的值则不会插入数据。

用法2:replace(object, search, replace)

作用是把object中出现search的全部替换为replace,例:

select replace(‘abc’, ‘b’, ‘x’);

例:把表table中的name字段中的aa替换为bb

update table set name=replace(name,'aa','bb')

注意:UPDATE和REPLACE的区别:

1)UPDATE在没有匹配记录时什么都不做,而REPLACE在有重复记录时更新,在没有重复记录时插入。

2)UPDATE可以选择性地更新记录的一部分字段。而REPLACE在发现有重复记录时就将这条记录彻底删除,再插入新的记录。也就是说,将所有的字段都更新了。

3.在插入大量数据之前,可以先将表锁定(Lock Tables)

为了提高数据插入的效率,可以考虑在插入之前先将表锁定。这主要是因为直到所有的INSERT语句都完成之后,索引缓存一次性刷新到磁盘中。通常情况下,有多少次INSERT语句就会有多少次索引缓存刷新到磁盘中的开销。为此在数据插入之前,将数据表进行锁定,就可以大幅度的提高数据插入的效率。当然,如果你可以用一个插入语句实现所有行的插入,则无需使用显式锁定语句。(针对非事务性表)

因此如果一个表的更新频率比较高时,那么可以使用Lock Tables选项来提高更新速度。

对于事务性表,要想更快地进行表插入,可以使用START TRANSACTION和COMMIT语句代替LOCK TABLES来提高更新速度。

4.可以对myisam表并行插入Concurrent_insert系统变量可以被设置用于修改concurrent-insert处理。

该变量默认设置为1。如果concurrent_insert被设置为0,并行插入就被禁用。如果该变量被设置为2,在表的末端可以并行插入,即便该表的某些行已经被删除。

5.使用插入延迟

如果客户无需等待插入完成的时候(即用户对插入数据的即时性要求可能并不是很高),此时就可以考虑采用插入延迟特性。Delayed的含义是让insert语句马上执行并返回,而数据被放在内存的队列中等待被插入,并没有真正的写入磁盘;这比每条语句都分别插入要快的多。

使用插入延迟的另一个好处就是从多个客户插入的情况会被绑定并记录在同一个block中。

默认情况下,在MySQL数据库中,更新操作比Select查询有更高的优先级。MySQL的默认的调度策略可用总结如下:

• 写入操作优先于读取操作。

• 对一张数据表的写入操作同一时刻只能发生一次,写入请求按照它们到达的次序来处理。

• 对一张数据表的多个读取操作可以同时地进行。

MySQL允许改变语句调度的优先级,它可以使来自多个客户端的查询更好地协作,这样单个客户端就不会由于锁定而等待很长时间。改变优先级还可以确保特定类型的查询被处理得更快。通过以下三种方式来修改它的调度策略:

• LOW_PRIORITY关键字应用于DELETE、INSERT、LOAD DATA、REPLACE和UPDATE。这个属性可以将某个特定的语句的优先级降低。如可以调低某个特定的更新语句或者插入语句的优先级。不过需要注意的是,这个属性只有对特定的语句有用。即其作用域只针对某个特定的语句,而不会对全局造成影响。

例:UPDATE [LOW_PRIORITY] tbl_name SET col_name1=expr1,col_name2=expr2,...

mysql中update用low_priority让update不锁定表

• HIGH_PRIORITY关键字应用于SELECT和INSERT语句。这个属性可以用来提高某个特定的Select查询语句的优先级。LOW_PRIORITY刚好相反,在所有其他用户对表的读写完成后才进行插入。这里需要注意,跟上面这个属性一样,这个作用域也只限于特定的查询语句。而不会对没有加这个参数的其他查询语句产生影响。也就是说,其他查询语句如果没有加这个属性,那么其优先级别仍然低于更新进程。

• DELAYED关键字应用于INSERT和REPLACE语句。

LOW_PRIORITY和HIGH_PRIORITY调节符影响那些使用数据表锁的存储引擎(例如MyISAM和MEMORY)。DELAYED调节符作用于MyISAM和MEMORY数据表。

通常情况下,某张数据表正在被读取的时候,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取者完成操作)。如果写入者正在等待的时候,另一个读取操作到达了,该读取操作也会被阻塞(block),因为默认的调度策略是写入者优先于读取者。当第一个读取者完成操作的时候,写入者开始操作,并且直到该写入者完成操作,第二个读取者才开始操作。

如果写入操作是一个LOW_PRIORITY(低优先级)请求,那么系统就不会认为它的优先级高于读取操作。在这种情况下,如果写入者在等待的时候,第二个读取者到达了,那么就允许第二个读取者插到写入者之前。只有在没有其它的读取者的时候,才允许写入者开始操作。理论上,这种调度修改暗示着,可能存在LOW_PRIORITY写入操作永远被阻塞的情况。如果前面的读取操作在进行的过程中一直有其它的读取操作到达,那么新的请求都会插入到LOW_PRIORITY写入操作之前。

SELECT查询的HIGH_PRIORITY(高优先级)关键字也类似。它允许SELECT插入正在等待的写入操作之前,即使在正常情况下写入操作的优先级更高。另外一种影响是,高优先级的SELECT在正常的SELECT语句之前执行,因为这些语句会被写入操作阻塞。

如果希望某一连接支持LOW_PRIORITY选项来处理,那么通过Set LOW_PRIORIT_UPDATES=1来设置连接变量,通过这个设置可以制定具体连接中的所有更新进程都是用比较低的优先级。但注意这个选项只针对特定的连接有用。对于其他的连接,就不适用。

如果希望所有支持LOW_PRIORITY选项的语句都默认地按照低优先级来处理,那么请使用--low-priority-updates选项来启动服务器。采用这个选项启动数据库时,系统会给数据库中所有的更新语句比较低的优先级。通过使用INSERT HIGH_PRIORITY来把INSERT语句提高到正常的写入优先级,可以消除该选项对单个INSERT语句的影响。

6.使用LOAD DATA INFILE从文本下载数据将比使用插入语句快20倍。

Load Date Infile是从一个文件中导入数据。如果采用这种方式的话,用户需要预先准备一个固定格式的文件。如果插入的数据量比较多,例如软件运行环境配置时可能会导入大量预配置数据时,此时使用Load Date Infile的方式能够取得比较好的性能。

执行LOAD DATA INFILE,数据插入到表中,由于无需更新表索引,因此这将非常快。

7.将大表分为多个小表来降低锁竞争

一些大表或频繁更新的表中,由于表的访问量较大,因此锁竞争也比较严重。此时,可以人为地将表合理分为多个小表,使表访问分散到多张表上,相互之间不会产生干扰时,就会降低表上锁的竞争,从而提高了访问效率。而当需要访问完整数据时,可以通过视图进行整合成一张表。

8.将索引文件和数据文件分在不同的磁盘上存放(利用建表中的选项)。

mysql实战优化之五: 更新/插入优化 sql优化的更多相关文章

  1. 使用游标循环进行SQL更新插入的SQL语句

    使用SQL中的循环,可以实现许多我们需要的操作,比如SQL更新操作.下面就为您介绍使用游标循环进行SQL更新插入的SQL语句写法,希望对您深入学习SQL更新有所帮助. --开始事务 BEGIN TRA ...

  2. MySql优化之存储引擎和sql优化

    存储引擎 使用的存储引擎 myisam / innodb/ memory myisam 存储: 如果表对事务要求不高,同时是以查询和添加为主的,我们考虑使用myisam存储引擎. ,比如 bbs 中的 ...

  3. Spring+SpringMVC+MyBatis+easyUI整合优化篇(十二)数据层优化-explain关键字及慢sql优化

    本文提要 从编码角度来优化数据层的话,我首先会去查一下项目中运行的sql语句,定位到瓶颈是否出现在这里,首先去优化sql语句,而慢sql就是其中的主要优化对象,对于慢sql,顾名思义就是花费较多执行时 ...

  4. SQL高级优化(四)之SQL优化

    SQL优化 一.SQL优化简介 解释:对于特定的要求,使用更有的SQL策略或索引策略,以达到让结果呈现的时间更短,从而提升操作效率的过程就是SQL优化. SQL优化包含在数据库级别优化中.我们平常所说 ...

  5. 7.30实习培训日志-SQL优化

    总结 今天早上考试,下午主要是老师引导我们学习SQL优化,晚上主要是同学的技术分享,杨松柏同学主要给我们分享了java的io的一些东西,c10k问题,bio(同步阻塞IO),NIO(同步非阻塞IO), ...

  6. 【重磅干货】看了此文,Oracle SQL优化文章不必再看!

    目录 SQL优化的本质 SQL优化Road Map 2.1 制定SQL优化目标 2.2 检查执行计划 2.3 检查统计信息 2.4 检查高效访问结构 2.5 检查影响优化器的参数 2.6 SQL语句编 ...

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

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

  8. mysql实战优化之一:sql优化

    1.选取最适用的字段属性 MySQL 可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得 ...

  9. mysql的慢查询实战+sql优化

    背景:使用A电脑安装mysql,B电脑通过xshell方式连接,数据内容我都已经创建好,现在我已正常的进入到mysql中 步骤1:设置慢查询日志的超时时间,先查看日志存放路径查询慢日志的地址,因为有慢 ...

随机推荐

  1. NumPy在数组上的迭代

    NumPy - 数组上的迭代 NumPy 包包含一个迭代器对象numpy.nditer. 它是一个有效的多维迭代器对象,可以用于在数组上进行迭代. 数组的每个元素可使用 Python 的标准Itera ...

  2. JNI_Z_05_方法的操作(没有String类型的参数)

    1.步骤: (1).获取 jclass (2).获取 method的id (3).调用 method ZC: 貌似 JNI里面 操作 类的方法,完全是 无视 访问权限的... 然而 static的方法 ...

  3. 新东方雅思词汇---8.3、apt

    新东方雅思词汇---8.3.apt 一.总结 一句话总结:本身为词根 adj. 恰当的:有…倾向的:灵敏的 本身为词根 英 [æpt]  美 [æpt]  adj. 恰当的:有…倾向的:灵敏的 n. ...

  4. base64编码的 文件 图片

    //图片 转为 base64编码的文本 private void button1_Click(object sender, EventArgs e) { OpenFileDialog dlg = ne ...

  5. 安装Charles报错

    去年用的是charles4.1.2版本,今年这个版本的安装包始终安装报错,不管公司电脑还是自己电脑........ 我的解决方案很Lower的.......... 登录Charles官网:https: ...

  6. uva 10125 二分

    https://vjudge.net/problem/UVA-10125 和之前做过的一道a+b+c=X的问题类似,不过这个要求多了a+b+c=d-->a+b=d-c  且abcd互不相等 我们 ...

  7. Kestrel 服务器部署多站点问题 (nginx 反向代理)

    Kestrel 作为微软的跨平台 web 服务器,有些地方用的好不是很熟. 作为一款嵌套到 dll 中的进程级 web 服务器,在同一台服务器上部署多站点确实还存在一点问题. 今天采用 nginx 做 ...

  8. STM32F103: NRF24L01

    看了两天的24l01的相关资料了,一直有点模糊,今天下午感觉有点懂了,在板子上调试成功了,但是还没进行通讯测试.stm32和arduino进行通信还没成功 ,:( 先把stm32的NRF24L01配置 ...

  9. 血的教训 password写成passward,教训应该从首页赋值 参数名

    血的教训 password写成passward,教训应该从首页赋值 参数名

  10. html 压缩成一行

    文章java gulp-htmlmin 减少下载的时间