mysql优化专题」90%程序员都会忽略的增删改优化(2)

补充知识点:操作数据语句优化的认识

通常情况下,当访问某张表的时候,读取者首先必须获取该表的锁,如果有写入操作到达,那么写入者一直等待读取者完成操作(查询开始之后就不能中断,因此允许读取者完成操作)。当读取者完成对表的操作的时候,锁就会被解除。如果写入者正在等待的时候,另一个读取操作到达了,该读取操作也会被阻塞(block),因为默认的调度策略是写入者优先于读取者。当第一个读取者完成操作并解放锁后,写入者开始操作,并且直到该写入者完成操作,第二个读取者才开始操作。因此:要提高MySQL的更新/插入效率,应首先考虑降低锁的竞争,减少写操作的等待时间。 (本专题在后面会讨论表设计的优化)本篇,要讲的优化是增删改。

一、NSERT语句:

基本:INSERT [INTO] 表名 [(字段列表)] VALUES (值列表)[, (值列表), …]

注意:

如果要插入的值列表包含所有字段并且顺序一致,则可以省略字段列表。

可同时插入多条数据记录!

REPLACE 与 INSERT 完全一样,可互换。

优化前例子:

优化策略:

(1)当我们需要批量插入数据的时候,这样的语句却会出现性能问题。例如说,如果有需要插入100000条数据,那么就需要有100000条insert语句,每一句都需要提交到关系引擎那里去解析,优化,然后才能够到达存储引擎做真的插入工作。上述所说的同时插入多条就是一种优化。(经测试,大概10条同时插入是最高效的)

优化后例子:

(2)将进程/线程数控制在2倍于CPU数目相对合适

(3)采用顺序主键策略(例如自增主键,或者修改业务逻辑,让插入的记录尽可能顺序主键)

(4)考虑使用replace 语句代替insert语句。(REPLACE语句请参考下文,有详细讲述)

二、DELETE语句:

DELETE FROM 表名[ 删除条件子句](没有条件子句,则会删除全部)

例子:

补充:Mysql中的truncate table和delete语句都可以删除表里面所有数据,但是在一些情况下有些不同!

例子:

truncate table gag;

(1)truncate table删除速度更快,,但truncate table删除后不记录mysql日志,不可以恢复数据。(谨慎使用)

(2)如果没有外键关联,innodb执行truncate是先drop table(原始表),再创建一个跟原始表一样空表,速度要远远快于delete逐条删除行记录。(思考:删除百万级数据的时候是否可用truncate table)

(3)如果使用innodb_file_per_table参数,truncate table 能重新利用释放的硬盘空间,在InnoDB Plugin中,truncate table为自动回收,如果不是用InnoDB Plugin,那么需要使用optimize table来优化表,释放空间。

truncate table删除表后,optimize table尤其重要,特别是大数据数据库,表空间可以得到释放!

(4)表有外键关联,truncate table删除表数据为逐行删除,如果外键指定级联删除(delete cascade),关联的子表也会会被删除所有表数据。如果外键未指定级联(cascde),truncate table逐行删除数据,如果是父行关联子表行数据,将会报错。

注意:

一个大的 DELETE 或 INSERT 操作,要非常小心,因为这两个操作是会锁表的,表一锁住,其他操作就进不来了。因此,我们要交给DBA去拆分,重整数据库策略,比如限制处理1000条。

另外,扩展下删除和索引的联系(关于索引优化,后面的查询优化也会讲解),由于索引需要额外的维护成本;因为索引文件是单独存在的文件,所以当我们对数据的增加,修改,删除,都会产生额外的对索引文件的操作,这些操作需要消耗额外的IO,会降低增/改/删的执行效率。所以,在我们删除数据库百万级别数据的时候,查询MySQL官方手册得知删除数据的速度和创建的索引数量是成正比的。所以我们想要删除百万数据的时候可以先删除索引(此时大概耗时三分多钟),然后删除其中无用数据,此过程需要不到两分钟,删除完成后重新创建索引(此时数据较少了)创建索引也非常快,约十分钟左右。与之前的直接删除绝对是要快速很多,更别说万一删除中断,一切删除会回滚。那更是坑了。

三、UPDATE语句:

UPDATE 表名 SET 字段名=新值[, 字段名=新值] [更新条件]

例子:

优化:更新多条记录(往后会结合MyBatics写个实例)

更新多条记录的多个值

(1). 尽量不要修改主键字段。(废话,反正我就从没改过..)

(2). 当修改VARCHAR型字段时,尽量使用相同长度内容的值代替。

(3). 尽量最小化对于含有UPDATE触发器的表的UPDATE操作。

(4). 避免UPDATE将要复制到其他数据库的列。

(5). 避免UPDATE建有很多索引的列。

(6). 避免UPDATE在WHERE子句条件中的列。


四、REPLACE语句:

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

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

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

用法:

(1)同INSERT

含义一:与普通INSERT一样功能

REPLACE INTO score (change_type,score,user_id) VALUES (‘吃饭‘,10,1),(‘喝茶‘,10,1),(‘喝茶‘,10,1);

含义二:找到第一条记录,用后面的值进行替换

REPLACE INTO score (id,change_type,score,user_id) VALUES (1,‘吃饭‘,10,1)

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

INSERTINTO score (change_type,score,user_id) VALUES (‘吃饭’,10,1),(‘喝茶’,10,1),(‘喝茶’,10,1);

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

(2)replace(object, search, replace),把object中出现search的全部替换为replace。

用法一:并不是修改数据,而只是单纯做局部替换数据返还而已。

SELECT REPLACE(‘喝茶‘,‘茶‘,‘喝‘)//结果: 喝喝123

用法二:修改表数据啦,对应下面就是,根据change_type字段找到做任务的数据,用bb来替换

UPDATE score SET change_type=REPLACE(change_type,‘做任务‘,‘bb‘)1

在此,做下对比:UPDATE和REPLACE的区别:

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

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

其实REPLACE更像INSERT与DELETE的结合。

时间: 2024-10-20 10:21:12

mysql优化专题」90%程序员都会忽略的增删改优化(2)的相关文章

「mysql优化专题」90%程序员没听过的存储过程和存储函数教学(7)

一.MYSQL储存过程简介(技术文): 储存过程是一个可编程的函数,它在数据库中创建并保存.它可以有SQL语句和一些特殊的控制结构组成.当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的.数据库中的存储过程可以看做是对编程中面向对象方法的模拟.它允许控制数据的访问方式.存储过程通常有以下优点: 1)存储过程能实现较快的执行速度. 如果某一操作包含大量的Transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多.因为存储过程是预编

「mysql优化专题」90%程序员面试都用得上的索引优化手册(5)

目录(技术文) 多关于索引,分为以下几点来讲解: 一.索引的概述(什么是索引,索引的优缺点) 二.索引的基本使用(创建索引) 三.索引的基本原理(面试重点) 四.索引的数据结构(B树,hash) 五.创建索引的原则(重中之重,面试必问!敬请收藏!) 六.百万级别或以上的数据如何删除 一.索引的概述 1)什么是索引? 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.更通俗的说,索引就相当于目录.当你在用新华字典时,帮你把目录撕掉了,

说一个MySQL里可能90%的程序员都会遇到的坑

说一个MySQL里可能90%的程序员都会遇到的坑最近我遇到了一个bug,我试着通过Rails在以"utf8"编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value: '\xF0\x9F\x98\x83 <-' for column 'summary' at row 1 我用的是UTF-8编码的客户端,服务器也是UTF-8编码的,数据库也是,就连要保存的这个字符串" 原文地址:https://blog.51c

90 % Java 程序员被误导的一个性能优化策略

我们经常看到一些 Java 性能优化的书或者理念,说不要在循环内定义变量,这样会占用过多的内存影响性能,而要在循环外面定义.接触 Java 这么久以来,相信很多 Java 程序员都被这种代码性能优化策略所误导. 看下面两个示例,示例1在循环外定义变量,示例2是在循环内定义变量. /** * 循环外定义变量 */ private static void outer() { Javastack javastack = null; for (int i = 0; i < 10; i++) { java

二分查找实现(Jon Bentley:90%程序员无法正确实现)

二分查找实现(Jon Bentley:90%程序员无法正确实现)作者:July出处:结构之法算法之道引言Jon Bentley:90%以上的程序员无法正确无误的写出二分查找代码.也许很多人都早已听说过这句话,但我还是想引用<编程珠玑>上的如下几段文字:“二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T 的范围,最终就可以找到它.一开始,范围覆盖整个数组.将数组的中间项与T 进行比较,可以排除一半元素,范围缩小一半.就这样反复比较,反复缩小范围,

如何优化C语言代码(程序员必读)

如何优化C语言代码(程序员必读) 5.减少运算的强度 可以使用运算量小但功能相同的表达式替换原来复杂的的表达式.如下: (1).求余运算. a=a%8; 可以改为: a=a&7; 说明:位操作只需一个指令周期即可完成,而大部分的C编译器的“%”运算均是调 用子程序来完成,代码长.执行速度慢.通常,只要求是求2n方的余数,均可使用 位操作的方法来代替. (2).平方运算 a=pow(a,2.0); 可以改为: a=a*a; 说明:在有内置硬件乘法器的单片机中(如51系列),乘法运算比求平方运算快得

利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)

最近看老罗的视频,跟着完成了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口: 1.public Connection getConnection()   获得数据库的连接 2.public boolean updateByPreparedStatement(String sql, List<Object>params)throws SQLException  更新数据库

「mysql优化专题」高可用性、负载均衡的mysql集群解决方案(12)

一.为什么需要mysql集群? 一个庞大的分布式系统的性能瓶颈中,最脆弱的就是连接.连接有两个,一个是客户端与后端的连接,另一个是后端与数据库的连接.简单如图下两个蓝色框框(其实,这张图是我在悟空问答解答别人的时候用Windows的自带画板画的,勿喷啊..) 版权归作者所有,哈哈 在客户端与后端中可以利用类似nginx的负载均衡解决(本专题是mysql优化,后面出高并发专题再详细讲解连接1的负载均衡),而数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担"能力范围内

「mysql优化专题」这大概是一篇最好的mysql优化入门文章(1)

优化,一直是面试最常问的一个问题.因为从优化的角度,优化的思路,完全可以看出一个人的技术积累.那么,关于系统优化,假设这么个场景,用户反映系统太卡(其实就是高并发),那么我们怎么优化? 如果请求过多,判定web服务器的压力过大,增加前端的web服务器,做负载均衡 如果请求静态界面不卡了,但是动态数据还是卡,说明MySQL处理的请求太多了,在应用层增加缓存. 数据库层其实是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担"能力范围内"的访问请求,所以,我们通过在服务