1.查看数据库,选中使用数据库,并查看数据库表,具体 *** 作命令如下:
show databases
use student
show tables
2.选择student数据库中的一张表stu_score,查看数据库表数据,并利用explain分析数据库表,如下图所示:
select * from stu_score
explain select * from stu_score
3.查看数据库使用索引的情况,使用命令:
show status like 'Handler_read%'
4.用于分析和存储表的关键字,分析的结果可以得到精准的信息,利用命令analyze,
analyze table stu_score
5.检查数据库表stu_score,检查表是否有错误,利用命令:
check table stu_score
6.优化数据库表,利用命令:
optimize table stu_score
官方版本测试到8.0.21依旧存在这个问题,Percona已经修复了,修复如下https://www.percona.com/blog/2018/03/27/analyze-table-is-no-longer-a-blocking-operation/
能力有限简单记录。
问题如下:
乍一看来,很是奇怪,这里没有出现我们经常遇到的flush table/flush table with read lock 堵塞,直接出现了 Waiting for table flush的堵塞,有点像
https://www.jianshu.com/p/b141585cd844
以前记录的文章中的案例2,但是其实并不一样,这里是由于analyze table语句造成的。构造非常简单(必须是社区版本,我使用的8.0.21),如下:
此时堵塞的情形就是Waiting for table flush
analyze table 除了更新我们的统计数据,实际上最后做了一个 *** 作如下(栈):
大概看一下做了什么,如下:
这里判断了是否当前table share正在使用,如果正在使用(很显然我们这个table share是不能直接释放的,因为有select一直持有它)那么将share版本的设置为0(share->clear_version(),实际上这个版本由全局变量refresh_version初始化),目的在于下次如果有使用表定义的时候需要重新打开table share。然后释放了当前没有使用的table cache(类型TDC_RT_REMOVE_UNUSED),如下:
当再次访问表的时候(open_table),会去判断如下是否有老的table share存在,如果存在则需要等待释放:
首先如果存在判断是否存在的老版本,判断是通过table share的版本和当前全局版本refresh_version进行比对,前面我们知道这里table share的版本已经设置为0,因此这里必然进入release_table_share环节,然后等待持有者的释放(案例窗口1的select查询),然后再次获取table share。等待栈如下:
进入waiting for table flush状态
Percona在上文中已经提到问题如下:
一个关键的修改点如下
官方版本:
Percona版本:
如此修改后analyze不会进入tdc_remove_table函数,那么table share的版本不会设置为0。因此如果使用官方版本小心本问题。
该命令有助于诊断性能低下的查询,尤其是查询是否使用了可用的索引。下面介绍下 这个命令显示的结果列的含义:
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
1️⃣Table:索引所在的表名
2️⃣Non_unique:0表示该索引是唯一索引,1表示该索引不是唯一索引
3️⃣Key_name:索引的名称
4️⃣Seq_in_index:索引列在索引中的位置,从1开始。对于组合索引来说,这个字段很重要。
5️⃣Column_name:索引列的名称
6️⃣Collation:索引列的值以什么方式存储在索引中。在MySQL中,A 表示有排序,B+树索引使用该方式;NULL 表示无序的,Heap索引使用该方式;
7️⃣Cardinality:索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机会就越大。 索引列所有值去重后的数量。该值除以该表的行数越接近1越好,如果非常小,则需要考虑是否可以删除该索引!
8️⃣Sub_part:数值 N 表示只对该列的前 N 个字符进行索引;NULL 表示索引整个列的值
9️⃣Packed:指示关键字是否被压缩,NULL 表示没有压缩
1️⃣0️⃣Null:索引列是否可以为空
1️⃣1️⃣Index_type:索引类型,BTREE 表示B+树索引。一共有四种(BTREE, FULLTEXT, HASH, RTREE)。
1️⃣2️⃣Comment:注释
1️⃣3️⃣Index_comment:注释
本语句用于分析和存储表的关键字分布。在分析期间,使用一个读取锁定对表进行锁定。这对于MyISAM、BDB和InnoDB表有作用。对于MyISAM表,本语句与使用 myisamchk -a 相当。
MySQL使用已存储的关键字分布来决定,当对除常数以外的对象执行联合时,表按什么顺序进行联合。本语句会返回一个含有以下列的表:
当需要删除一个索引时,使用语句:
需要特别注意的是,当使用组合索引时,where 语句中最常使用的字段名,应该放在组合索引中的第一个。比如,以下组合索引的定义:
基本就可以判断,id,book,author 作为 where 的查询条件的频率,从大到小应该是:id >book >author。还需要知道的一点是,触发组合索引的条件是向后匹配组合索引中的字段。还是看上面这个组合索引的例子,当查询语句的 where 条件包括下面任何一种情况,才会触发组合索引:
如果是以下任何一种情况,则不会触发组合索引:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)