MySQL 及调优
存储引擎的种类
MySQL 中存在多种存储引擎,比如:
- InnoDB
- 支持事务;
- 支持外键;
- 同时支持行锁和表锁。
- 适用场景:经常更新的表,存在并发读写或者有事务处理的业务场景。
- MyISAM
- 支持表锁(插入更新操作会锁表);
- 不支持事务;
- 拥有较高的插入和查询速度。
- 适用场景:只读类的数据分析的业务场景。
- MEMORY
- 所有数据存储在内存中,读写速度快;因此数据库重启,数据会消失。
- 适用场景:临时表。
如何选择合适的存储引擎?
- 数据一致性要求较高,需要事务,选择 InnoDB
- 数据查询多,更新少,对查询性能要求较高,选择 MyISAM
- 用于查询的临时表,选择 MEMORY
索引种类
InnoDB 中有 3 中索引类型:
- 普通索引,没有任何限制
- 唯一索引,要求键值不能重复,
主键索引是特殊的唯一索引,主键索引还要求键值不能为空 - 全文索引,大文本的场景下,可以用全文索引解决 like 查询效率低的问题,全文索引只有 char、varchar、text 类型的字段才能创建
create table t_user(
id bigint(13) not null,
name varchar(20),
remark varchar(200),
primary key(id),
fulltext index(remark) -- 创建全文索引
);
-- 使用全文索引
select * from t_user where match(remark) against('xkcoding' IN NATURAL LANGUAGE MODE);
InnoDB 锁
InnoDB 支持表级别的锁,也支持行级别的锁。锁的粒度,表锁大于行锁;加锁的效率,表锁高于行锁;锁的并发性能,行锁优于表锁。
共享锁
共享锁是个行级别的锁,主要用于读取数据的场景,也叫读锁,不要在获取了读锁之后去写数据,可能会出现死锁的情况,多个事务可以共享一把读锁。
添加读锁:
select * from t_user lock in share mode;
排他锁
排他锁是个行级别的锁,主要用于操作数据的场景,也叫写锁。只要一个事务获取了一行数据的写锁,那么其他事务就不能再获取这一行数据的读锁和写锁了。
添加排他锁:
① 数据库会默认为增删改操作加上排他锁
② 使用 FOR UPDATE 语法
select * from t_user for update;
行锁的原理
InnoDB 的行锁,是通过锁住索引来实现的。如果一个表没有创建索引怎么办?如果定义了主键,InnoDB 会选择主键作为聚集索引。
SQL 优化
sql 优化要从几个方面考虑:sql 语句优化、表结构优化、架构优化。
SQL 语句优化
看执行计划
定位到慢 sql 后,通过 explain 分析 sql 执行计划。
explain 得到的结果,如果存在多条记录,执行顺序会根据 id 从大到小排序,排序靠前的先执行。
执行计划的结果要重点关注的字段有:type、rows、filtered、extra。
type 字段表示连接类型,包括:system > const > eq_ref > ref > range > index > all,一般来说,至少需要达到 range 级别,尽量保证 ref 级别,all 和 index 都是需要进行优化的。
- all 全表扫描,Full Table Scan。
- index 索引全扫描,Full Index Scan,结合回表去理解。
- range 索引范围扫描,常用于 <,<=,>=,between,in 等操作。
- ref 使用非唯一索引扫描或唯一索引前缀扫描,返回单条记录,常出现在关联查询中。
- eq_ref 类似 ref,区别在于使用的是唯一索引,使用主键的关联查询。
- const/system 单条记录,系统会把匹配行中的其他列作为常数处理,如主键或唯一索引查询。
Extra:
- Using filesort:MySQL 需要额外的一次传递,以找出如何按排序顺序检索行。通过根据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行。
- Using temporary:使用了临时表保存中间结果,性能特别差,需要重点优化。比如使用了 union。
- Using index:表示相应的 select 操作中使用了覆盖索引(Coveing Index),避免访问了表的数据行,效率不错!如果同时出现 using where,意味着无法直接通过索引查找来查询到符合条件的数据。
- Using index condition:MySQL5.6 之后新增的 ICP,using index condtion 就是使用了ICP(索引下推),在存储引擎层进行数据过滤,而不是在服务层过滤,利用索引现有的数据减少回表的数据。
SQL 优化场景
1、不要使用select *
首先,数据库解析 * 有时间消耗;其次,使用 * 可能导致索引失效,比如 where 条件是大于,或者 in 等范围条件的时候,如果查询的列只有带索引的列时,执行计划会走索引,否则全表扫描。
2、建索引
索引创建原则:
- 在用于 where 条件过滤、order by 排序的字段创建索引
- 在 join 的 on 字段创建索引
- 索引的个数不要过多,浪费空间,过多的索引还会导致更新变慢
- 在离散度高的字段创建索引
- 频繁更新的值,不要作为主键或者索引
- 联合索引最好将离散度高的字段放在前面,联合索引最左匹配原则
- 创建联合索引,而不是去修改单列索引
- 不建议使用无序的值作为索引
- 字段较长时,可以通过截取字段的前一部分来创建索引,具体截取多少,可以通过计算离散度,找到最合适的长度
索引使用原则:
联合索引最左匹配原则:建立联合索引时,把最常用的字段放在最左边。假设
index(a,b)建立了 a 和 b 的联合索引,查询条件where a = ? and b = ?和where a = ?都可以匹配该索引,而where b = ?这样子就无法使用当前索引了。优先使用覆盖索引:非主键索引会先通过索引查询到主键索引,再通过主键索引找到数据,比单独的主键索引的查询多扫描了一颗索引树,这个过程叫做回表。(MySQL 覆盖索引详解)
如果需要查询的字段从索引中直接可以获取,不需要回表操作,那么此时就用到了覆盖索引。执行计划的 Extra 如果有 Using Index 就表示使用了覆盖索引。假设创建
index(a,b)我们查询的时候select b from t where a = ?,这就用到了覆盖索引。需要注意的是select *的操作用不到覆盖索引。
索引失效场景:
- 索引字段使用函数(
replace/substr/concat/sum/count/avg)、表达式、或者计算(+ - * /) - 隐式转换,比如字符串类型的字段未加单引号
- like 条件出现
%在左,like '%xxx' - 反向查询,比如 NOT LIKE 则使用不到索引,但是
<>、NOT IN在某些情况下可以使用到索引
3、少用 union,尽量用 union all
union 去重是基于临时表,临时表的特性是,如果在 InnoDB 上设置的缓存够大则使用内存来完成临时表的高效处理;如果union 的结果特别大,超出了内存能够承载的范围,MySQL 会自动创建 MyISAM 引擎表,MyISAM 表是在磁盘上处理的, IO 效率变差,造成 sql 执行效率低。如果一定要用 union,可以加 limit 限制结果集数量。
4、大分页
数据量极大的情况下,分页尽量减少偏移量。比如:
-- 大偏移量
select * from t_user limit 900000,10;
-- 修改为先过滤,再 limit
select * from t_user where id >= 900000 limit 10;
5、选择合适的字符类型
6、关联查询时小表驱动大表,外键要加索引
嵌套循环联接(Nest Loop Join)与编程中的二层嵌套类似。外表(驱动表)中的每一条记录与内表(被驱动表)中的记录进行比较判断。
- 小表驱动大表:联接查询的执行计划,按上下顺序,第一个是驱动表。驱动表的大小直接决定关联查询时的效率。MySQL 会优先选择小表作为驱动表优先执行,有子查询时会先执行子查询,再执行外层查询。
- 外键要加索引:多表关联查询时,只有在外键上也加索引,关联表的索引才能生效。通过建索引能解决大部分的关联查询的效率问题,只要做好单表的数据查询优化,在主外键关联都建索引的情况下,MySQL 优化器会自动选择最优的驱动表,这样执行效率就不会低。如果关联表太多,驱动表的选择可能会有问题,所以一些大厂会建议关联查询的表最好不要超过 3 个。
表结构优化
- 为不同的业务选择合适的存储引擎,查询插入操作多的业务选择 MyISAM,临时数据选择 MEMORY,并发大更新操作多的业务选择 InnoDB。
- 尽量选择合适的数据类型和数据长度。
- 非空字段定义为 NOT NULL,通过提供默认值、特殊值的方式,代替 NULL,减少 NULL 类型的存储。
- 不要使用外键。
- 尽量不使用触发器、视图。视图也是查表来的,不能优化查询速度,而且在sql中会与表名混淆,增加复杂度。
- 不要使用数据库存储二进制文件或者大文件存储,尽量使用文件服务器解决,数据库只存储文件的相对路径。
架构优化
- 引入缓存服务,如 Redis,降低查询对数据库带来的压力。
- 分库分表,垂直分库减少并发压力,水平分表解决存储瓶颈。垂直分库是按照业务拆分成不同的数据库。水平分库分表是按照一定规则分不到不同的数据库中。
- 使用主从复制,从而实现读写分离,可以一定程度减轻数据库访问压力。但是需要注意主从数据一致性问题。
面试题
如何快速往 MySQL 中插入 100W 行的数据?
点击查看答案
先建立一张存储引擎为 MyISAM 的表,往里插入数据,插入完成之后,修改存储引擎为 InnoDB。
主从复制的原理?如何解决主从复制带来的数据一致性问题?
点击查看答案
主从复制原理:从服务器读取主服务器的 binlog 文件,然后执行一遍。
默认情况下,MySQL 主从复制是异步复制,master 不关注 slave 是否写入成功。
如果要保证主从的一致性,可以采用全同步复制,也就是 master 需要等待 slave 写入成功之后,再返回给客户端。这样会导致 master 性能下降。
介于异步复制和全同步复制之间,有一种叫做半同步复制。master 执行完客户端提交的事务后,不立即返回给客户端,而是等待至少一个 slave 接收到 binlog 同时写入到 relay log 才返回给客户端。
如何避免死锁的情况
点击查看答案
- 批量操作单表时,先对数据进行排序(避免出现等待环路)
- 申请足够级别的锁,如果操作数据,申请排他锁
- 尽量使用索引访问数据,避免锁表
- 尽量拆分大事务为小事务
- 尽量使用等值查询,减少范围查询
参考资料
MySQL 及调优的更多相关文章
- mysql技术调优资料整理
1,15 个有用的 MySQL/MariaDB 性能调整和优化技巧 2,MariaDB设置主从复制 3,CentOS6.4安装mysql2redis http://www.cnblogs ...
- MySQL性能调优——锁定机制与锁优化分析
针对多线程的并发访问,任何一个数据库都有其锁定机制,它的优劣直接关系着数据的一致完整性与数据库系统的高并发处理性能.锁定机制也因此成了各种数据库的核心技术之一.不同数据库存储引擎的锁定机制是不同的,本 ...
- MySQL性能优化总结___本文乃《MySQL性能调优与架构设计》读书笔记!
一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存储引擎 MyISAM存储引擎 ...
- MySQL 性能调优之存储引擎
原文:http://bbs.landingbj.com/t-0-246222-1.html http://bbs.landingbj.com/t-0-245851-1.html MySQ ...
- MySQL性能调优的10个方法 - mysql数据库栏目
摘要: https://edu.aliyun.com/a/29036?spm=5176.11182482.related_article.1.hbeZbF 摘要: MYSQL 应该是最流行了 WEB ...
- MySql(十一):MySQL性能调优——常用存储引擎优化
一.前言 MySQL 提供的非常丰富的存储引擎种类供大家选择,有多种选择固然是好事,但是需要我们理解掌握的知识也会增加很多.本章将介绍最为常用的两种存储引擎进行针对性的优化建议. 二.MyISAM存储 ...
- MySQL性能调优与架构设计——第 18 章 高可用设计之 MySQL 监控
第 18 章 高可用设计之 MySQL 监控 前言: 一个经过高可用可扩展设计的 MySQL 数据库集群,如果没有一个足够精细足够强大的监控系统,同样可能会让之前在高可用设计方面所做的努力功亏一篑.一 ...
- MySQL性能调优与架构设计——第 17 章 高可用设计之思路及方案
第 17 章 高可用设计之思路及方案 前言: 数据库系统是一个应用系统的核心部分,要想系统整体可用性得到保证,数据库系统就不能出现任何问题.对于一个企业级的系统来说,数据库系统的可用性尤为重要.数据库 ...
- MySQL性能调优与架构设计——第 16 章 MySQL Cluster
第 16 章 MySQL Cluster 前言: MySQL Cluster 是一个基于 NDB Cluster 存储引擎的完整的分布式数据库系统.不仅仅具有高可用性,而且可以自动切分数据,冗余数据等 ...
- MySQL性能调优与架构设计——第 15 章 可扩展性设计之Cache与Search的利用
第 15 章 可扩展性设计之Cache与Search的利用 前言: 前面章节部分所分析的可扩展架构方案,基本上都是围绕在数据库自身来进行的,这样是否会使我们在寻求扩展性之路的思维受到“禁锢”,无法更为 ...
随机推荐
- 一文讲透消息队列RocketMQ实现消费幂等
这篇文章,我们聊聊消息队列中非常重要的最佳实践之一:消费幂等. 1 基础概念 消费幂等是指:当出现 RocketMQ 消费者对某条消息重复消费的情况时,重复消费的结果与消费一次的结果是相同的,并且多次 ...
- 从Redis读取.NET Core配置
在本文中,我们将创建一个自定义的.NET Core应用配置源和提供程序,用于从Redis中读取配置.在此之前,您需要稍微了解一些.NET Core配置提供程序的工作原理,相关的内容可以在Microso ...
- ElasticSearch之Close index API
关闭指定的索引. 索引关闭之后: 停止对读.写操作的响应. 停止检索操作的响应. 在索引关闭前,允许执行的操作,关闭之后均不允许执行. ElasticSearch取消对索引的相关维护操作,包含内存中的 ...
- 关于腾讯地图geolocation.getLocation 经常定位失败,定位时间过长的解决方法
今天遇到个项目,腾讯地图定位出现问题,导致地图无法呈现出最近的目标 这是正常的效果,之前一直出现贵州等地点的信息,查看控制台的网络后,发现腾讯的定位失败,要么就是定位时间过长,要20S左右,但是换ED ...
- thymeleaf特殊字符输出转义
thymeleaf特殊字符输出转义,字符串包括/@#¥%&*,正常来说他们输出会被转义掉.主要是使用了th:inline="javascript"标签,它会自动安全转义字符 ...
- 动态规划问题(六)最长公共子序列(LCS)
问题描述 给你两个字符串,要求得到这两个字符串的最长公共子序列长度. 比如:对于输入的字符串 S1 "AGGTAB" 和 S2 "GXTXAYB",它们 ...
- 2021-01-04:mysql里的innodb引擎的数据结构,你有看过吗?
福哥答案2021-01-04: 面试官刚开始问我看过mysql源码没,然后问了这个问题.回答B+树,过不了面试官那关. 答案来自<MySQL技术内幕 InnoDB存储引擎 第2版>第四章, ...
- 3种依赖管理工具实现requirements.txt文件生成
1.pip 实现方式 要使用 pip 生成 requirements.txt 文件,可以使用以下命令: pip freeze > requirements.txt 这个命令会将当前环境中 ...
- 【华为云技术分享】空间异常即刻诊断,华为云数据管理服务DAS又出新招
摘要:华为云数据管理服务DAS提供的云DBA智能化运维平台于日前发布了空间&元数据分析特性,支持查看实例空间异常列表.实例空间概况.数据库列表信息,帮助用户及时发现数据库中的空间和元数据异常, ...
- 如何正确使用Python临时文件
摘要:临时文件通常用来保存无法保存在内存中的数据,或者传递给必须从文件读取的外部程序.一般我们会在/tmp目录下生成唯一的文件名,但是安全的创建临时文件并不是那么简单,需要遵守许多规则. 1.前言 临 ...