导图社区 MySQL
关于MySQL的思维导图,分享了 架构介绍、索引优化、查询截取分析、MySQL锁机制、主从复制的知识,快来看看吧!
编辑于2023-05-21 20:42:33MySQL高级
架构介绍
MySQL存储引擎
命令
查看:show engines
查看默认:show variables like '%storage_engine%';
InnoDB和MyISAM
索引优化
性能下降SQL慢 执行时间长 等待时间长
SQL语句写的烂
索引失效
单值索引
user表的name字段建立名为idx_user_name的索引
create index idx_user_name on user(name)
复合索引
create index idx_user_nameEmail on user(name,email)
关联查询太多join
服务器调优及各个参数设置
常见通用的join查询
SQL执行顺序
手写
select distinct * from table_A <join_type> join table_B on <join条件> where <where条件> group by ... having ... order by ... limit ...
机读
1 from table_A 2 on ... 3 <join_type> join table_B 4 where ... 5 group by ... 6 having ... 7 select 8 distinct ... 9 order by ... 10 limit ...
join
索引介绍
性能分析
MySQL Query Optimizer(MySQL自带的查询优化器)
MySQL常见瓶颈
CPU饱和
数据装入内存 或 从磁盘读取数据的时候
I/O瓶颈
装入数据远大于内存容量的时候
服务器硬件性能瓶颈
top,free,iostat,vmstat 来查看系统性能状态
Explain
是什么(执行计划)
使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的,分析你的查询语句或是表结构的性能瓶颈
能干嘛
表的读取顺序
数据读取操作的操作类型
哪些索引可以使用
哪些索引被实际使用
表之间的作用
每张表有多少行被优化器查询
怎么玩
explain+SQL语句
执行计划包含的信息
表头: id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
p
字段解释
id
id相同,执行顺序由上至下
id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先执行
id相同不同,同时存在
id如果相同,可以认为是一组,从上往下顺序执行; 在所有组中,id值越大,优先级越高,越先执行 derived:衍生【虚拟表】
select_type
类型
SIMPLE
简单的select查询,不包含子查询或者UNION
PRIMARY
查询中若包含任何复杂的子部分,最外层查询被标记为PRIMARY
SUBQUERY
在select或where列表中包含了子查询
DERIVED
在from列表中包含的子查询被标记为derived(衍生、临时表) MySQL会递归执行这些子查询,把结果放在临时表里
UNION
若第二个select出现在union之后,则被标记为union; 若union包含在from子句的子查询中,外层select将被标记为derived
UNION RESULT
从union表获取结果的select
查询类型主要用于区别:普通查询、联合查询、子查询等复杂查询
table
type
p
type显示的是访问类型,是较为重要的一个指标
结果值:从最好到最坏依次是:system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>all
一般来说,得保证查询至少达到range级别,最好能达到ref
查询使用了何种类型:从最好到最差:
system>const>eq_ref>ref>range>index>all
system:表示只有一行记录(等于系统表),这是const类型的特列,平时不会出现,可以忽略不计
const:表示通过索引一次就找到了,const用于比较primary key【主键】或者unique索引【唯一索引】。因为只匹配一行数据,所以很快;如将主键置于where列表中,MySQL就能将该查询转换为一个常量
eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配。常用于主键或者唯一索引扫描
ref
非唯一性索引扫描,返回匹配某个值的所有行,本质上也是一种索引访问,它返回所有匹配某个值的行,然而,它可能会找到多个符合条件的行,所以它应该属于查找和扫描的混合体
range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引;一般就是where语句中出现了between、<、>、in等的查询;这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引
index
Full Index Scan,index与all区别:index类型只遍历索引树。这通常比all快,因为索引文件通常比数据文件小。【也就是说:虽然all和index都是读全表,但是index是从索引中读取的,而all是从硬盘中读取的】
all
Full Table Scan,遍历全表以找到匹配行
备注:一般来说,得保证查询至少达到range级别,最好能达到ref。
possible_keys
显示可能应用在这张表上的索引【一个或者多个】。 查询涉及到的字段上若存在索引,则改索引将被列出,但是不一定被查询实际使用
key
实际使用的索引。如果为null,则没有使用索引
查询中若使用了覆盖索引,则该索引仅出现在key列表中
覆盖索引:所查询的字段和所建的索引字段以及顺序都是一致的; eg: create index inx_col1_col2 on t(col1,col2); -- 建复合索引 select col1,col2 from t1; -- 查询的字段与所建的复合索引重合
p
可用于判断索引失效问题
key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。
ref
rows
Extra
热身Case
索引优化
索引分析
索引失效(应该避免)
1> 全值匹配我最爱
2> 最佳左前缀法则
带头的不能死 即复合索引的第一个索引列 没有用到 整个索引失效
如果索引了多列(复合索引),要遵守最左前缀法则.即 查询从索引的最左前列开始且不跳过索引中的列
3> 不在索引列上做任何操作(计算,函数,[自动或手动]类型转换),会导致索引失效而转向全表扫描
4> 储存引擎不能使用索引中范围条件右边的列
即索引列中范围条件右边的索引失效, 左边的 范围索引本身 还是有用的
5> 尽量使用覆盖索引(只访问索引的查询[索引列和查询列一致]),减少select *
6> mysql在使用不等于(!=或<>)的时候无法使用索引会导致全表扫描
7> is null,is not null 也无法使用索引
8> like以通配符开头【'%aaa' 或 '%aaa%'】,mysql索引失效会变成全表扫描的操作。【'aaa%'】这种不会全表扫描,索引不会失效
问题: 解决like '%字符串%' 索引失效的方法?
建立覆盖索引
定义 : 如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’。即只需扫描索引而无须回表。 create index idx_user_nameAge on table_user(name,age); 建立复合索引 idx_user_nameAge select id[主键] 。。。 索引 不失效 select name 。。。 索引 不失效 select age 。。。 索引 不失效 只要是 查询 id name age 这三个 随便组合 索引 都 不会失效 select * 。。。 索引失效 select id ,name,email 。。。 索引失效
9> 字符串不加单引号{存在隐式类型转换【88--->'88'】}索引失效
10> 少用or,用他来连接时索引会失效
一般性建议
查询截取分析
总结 1、慢查询的开启并捕获 2、explain+慢SQL分析 3、show profile查询SQL在MySQL服务器里面的执行细节和生命周期情况 4、SQL数据库服务器的参数调优
MySQL锁机制
锁是计算机协调多个进程或线程并发访问某一资源的机制。
操作类型分【读锁/写锁】
读锁【共享锁】:针对同一份数据,多个读操作可以同时进行而不会相互影响
表加读锁
读锁会阻塞写,但不会阻塞读。写锁会阻塞读和写
写锁【排他锁】:当前写操作没有完成前,它会阻断其他写锁和读锁
表加写锁
操作粒度分【表锁/行锁】
表锁【偏读】
Myisan的读写锁调度是写优先,这也是Myisan不适合做写为主表的引擎。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远的阻塞。
特点
偏向MyISAM存储引擎,开销小,加锁块;无死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
命令
手动增加表锁
lock table 表名1 read/write,表名2 read/write,其他;
lock table A read,B write; #A读锁,B写锁
查看表上加过的锁
show open tables;
释放表锁
unlock tables;
表锁分析
1、看哪些表被加锁了
show open tables;
2、如何分析表锁定
show status like 'table%';
查看table_locks_waited
出现表级锁定争用而发生等待的次数(不能立即获取锁的次数,每等待一次锁值+1),此值高则说明存在着较严重的表级锁争用情况;
查看table_locks_immediate
产生表级锁定的次数,表示可以立即获取锁的查询次数,每立即获取锁值+1;
查看二者的状态变量来分析表锁定
事务
事务及其ACID属性
并发事务处理带来的问题
更新丢失
当两个或多个事务选择同一行时,然后基于最初选定的值更新改行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新的问题——最后的更新覆盖了由其他事务所做的更新。 如果在一个程序员完成并提交事务之前,另一个程序员不能访问同一文件,则可避免此问题。
脏读
一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此作进一步的处理,就会产生未提交的数据依赖关系,即”脏读“。 事务A读取到了事务B已修改但尚未提交的数据,还在这个数据基础上做了操作。此时,B事务回滚,A读取的数据无效,不符合一致性要求。
不可重复读
一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象即是“不可重复读”。 事务A读取到了事务B已经提交的修改数据,不符合隔离性。
幻读
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象即“幻读”。 事务A读取到了事务B提交的新增数据,不符合隔离性。 幻读和脏读有点类似: 脏读:是事务B里修改了数据; 幻读:是事务B里新增了数据。
事务隔离级别
事务的隔离级别
查看数据库事务隔离级别
show variables like 'tx_isolation';
MySQL默认事务隔离级别
可重复读(repeatable read)
行锁【偏写】
特点
偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高
innoDB和MyISAM最大的不同:一是支持事务;二是采用了行级锁
行锁基本演示
索引失效导致行锁变表锁
1、a【int】 b【varchar】两字段建立普通索引; 2、session-1、session-2都set autocommit = 0;
间隙锁危害
如何锁定一行
总结
Innodb存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗比表级锁定会更高些,但是在整体并发处理能力方面要远远优于MyISAM的表级锁定。当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有明显的优势了。
行锁分析
命令:show status like 'innodb_row_lock%'; 分析系统上行锁的争夺情况
p
优化建议
尽可能数据检索都通过索引来完成,避免索引失效行锁升级为表锁
合理设计索引,缩小锁的范围
减少检索条件,避免间隙锁
控制事务大小,减少锁定资源量和时间长度
尽可能低级别事务隔离
页锁
主从复制
基本原理
slave会从master读取binlog【二进制文件】来进行数据同步
三步骤+原理图
基本原则
每个slave只有一个master
每个slave只能有一个唯一的服务器ID
每个master可以有多个slave
复制的最大问题:延时
一主一从配置
浮动主题