Mysql-Explain/处理锁表
锁表问题
方式1
1.通过进程查看哪些进程处于等待状态,执行如下sql即可
show PROCESSLIST; -- 执行完毕之后会发现有一个State列,这列里面如果包含类似lock或者wait之类的,就说明这个进程处于等待或被锁了
2.杀死被锁住的进程,执行如下sql即可
kill 6666; -- 其中示例6666是上述步骤1中查询结果的'id'列,如果批量杀死,建议使用可以列编辑的软件,批量生成sql
方式2
和方式1对比,不如方式1暴力简单,方式1可能导致数据不一致,但我个人认为还是方式1简单,数据就算不一致,后续手动补偿也可以了
1.查看被锁住的表,执行如下sql即可
SHOW OPEN TABLES WHERE In_use>0; -- 如果没有任何表被锁住,则查询结果没有任何记录
2.解锁表
FLUSH TABLES表名 WITH READ LOCK:
Explain相关
本文将持续更新
explain是mysql的一个工具,为了学习和测试,需要关闭mysql的衍生表优化功能,使用下面的语句即可关闭衍生表合并
// off改成on将会开启衍生表合并,默认=on
set session optimizer_switch='derived_merge=off';
显示mysql推荐给我们的sql语句
explain 我们自己的sql;
show warnings;
select_type:查询结果的类型
SIMPLE:查询结果直接返回给用户,或者作为in,on后边的条件
DERIVED:查询结果给其他查询使用,就是接到from关键字后面
SUBQUERY:查询结果作为其他查询的条件,这些条件包括=,>,<
DEPENDENT SUBQUERY:查询结果作为其他查询的not in
UNION:大概的看了一下union关键字后边的select都是union类型
PRIMARY:目前我尚未明白该类型的含义 TODO
type:表示关联类型或者访问类型,既mysql决定如何查找表中的行,查找数据行记录的大概范围
笔记:type我猜应该是对条件的描述,也就是说是where后面的语句的描述????
效率上从高到低:system>const>eq_ref>ref>range>index>ALL
system/const:where条件后面的字段全都是唯一索引,且运算符都是=
eq_ref:目前我尚未明白该类型的含义 TODO
ref:表示on后边有一个是索引,但不是唯一索引
range:表示是一个范围查找,关键字in,或者>,<,>=,<=,并且条件字段带索引,如果没索引,即使是范围查找,也会变成All
index:扫描全表,但是是使用全表的索引扫描,意思查询的所有字段都带索引
all:扫描全表,使用全表扫描,而不是全表的索引扫描,意思是查询的某些字段不带索引
key
查询时候用到的索引
key_length
确定使用了哪些索引,假设现在有联合索引a_b,a占4个字节,b占4个字节,如果key_length=4,则说明使用了a索引,如果key_length=8,则说明ab都使用了,这里可以看出mysql遵循了最左原则
extra
Using index:表示查询结果的每一列都有索引,性能较高
Using filesort:order by A,A列没有索引的时候,会显示filesort,性能较低
Using where:where name=xxx,name没有索引则会显示Using where,性能较低
Using index condition:查询结果中有的列没索引,但是where条件中有索引
select * from 表 where data(时间列)='2020-09-22'
改成
where data(时间列)>='2020-09-22' and data(时间列)<='2020-09-22'
假设abc是联合索引
where a=x and b>x and c=x
因为b>x是范围查找,所以索引只走ab,不走c
is null,is not null,一般情况下不走索引,原因在于null和其他比较,结果还是null,导致没办法比较大小,由于这种情况的存在,所以mysql不建议使用可以为空的字段,建议所有字段都有默认值,因为is null和is not null作为where本身就不合理
not in,一般情况下不走索引
like,如果是like '%xxx’则不走索引,如果like ‘xxx%‘则走索引,但是实际业务场景会出现这种模糊查询’%xxx%’,此时应该使用覆盖索引去优化,也就是说select a,b,c的时候,abc三个必须全都带索引,这就叫覆盖索引,假设只有ab有索引,c没索引,那么此时无解,只能使用一些搜索引擎来解决,比如es
字符串不加引号,不会走索引,比如where name=1000,不会走索引,因为涉及到强转,mysql会给name字段加一个cast函数,字段加函数之后,不会走索引,这是本质原因
查看mysql缓存命中率
执行如下sql
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
会得到两个字段,然后计算未命中率 = Innodb_buffer_pool_reads/ Innodb_buffer_pool_read_requests,命中率越大越好,都说能达到百分之99最好,但是我日常命中率也就95%左右,也够用了
更多推荐



所有评论(0)