赞
踩
执行计划又叫explain计划。
查询中,查询子任务操作的顺序,若序号相同则从上到下执行;若顺序不同,数值越大,执行优先级越高.
表示查询中每个查询子任务的类型
表别名
mysql从表中找到所需行的方式
可能会用到的索引
实际会用到的索引
作为索引的字段的长度ref在key列所记录的索引中,查找值所用的列或常量rows扫描的行数
- 如果索引中已经包含你所有查找的所有字段,就没必要回表(读磁盘查表),这就叫覆盖索引。
- 由于innodb使用了聚簇索引,且innodb的二级索引在叶子节点中保存了行的主键,所以若二级索引可以覆盖查询,就能省去反查主键的消耗。
- 覆盖索引要求索引中必须存储索引列的值,而hash索引、空间索引、全文索引都不支持存储索引列的值,所以不是所有索引都支持覆盖索引,mysql只支持btree做覆盖索引。
using index condition
先读取索引元组,判断是否要下推进行全表扫描。(什么是索引下推)
using where
表示查询可受益于不同的索引,即where字句里包含索引列,mysql服务器将在存储引擎检索后再进行过滤。
using filesort
表示mysql将会使用外部索引排序(什么是外部索引排序),但mysql提供了两种外部索引排序,且并不会告知我们到底使用了那种,以及是在内存还是在磁盘完成排序。
select
*
from
xxxx
where
`is_deleted` = 0
and `task_id` = ?
and `type` in (?,?,?,?,?,?)
order by
`id`
limit ?,?
执行计划
[{"ref":"const",
"filtered":4.0,
"Extra":"Using index condition; Using where; Using filesort",
"select_type":"SIMPLE",
"id":1,
"type":"ref",
"rows":201156,
"possible_keys":"key",
"table":"xxxx",
"key":"key",
"key_len":"8" }]
in查询会走索引,但随着in的范围变大,效率会主键下降为全表扫描。
不论在Mysql5还是Mysql8,explain select * from x limit 10,执行计划在预测扫描行数时都会剔除limit子句。
MySQL是按照Page存储的,每个Page都有自己的元数据,会记录行数。
假设select * from x where sex = ‘male’,性别为男性的记录实际占10页半。
但是
mysql5以前,预估扫描行数,只会采样2页,首页及尾页
mysql5以后,预估扫描行数,只会采样10页,首页 + 尾页 + 首页往后8页预估Rows = ((第1页 + 第2…第9页 + 最后1页)/10)*10页半,这就出现误差了。
5.1.10 Server Status Variables
关注这几个参数
rnd_next过大需要优化;
read_key、read_next、read_prev太大也不行,这说明扫描了很多索引值才找到记录,也需要优化;
通过show status可以较为准确的知道扫描了多少行,同时不会像explain一样忽略limit子句;
flush status; # last_name字段不是索引 select * from employees where last_name = 'Facello'; SHOW SESSION STATUS LIKE "Handler%"; +----------------------------+--------+ | Variable_name | Value | +----------------------------+--------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 2 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 1 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 0 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 300025 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+--------+ 18 rows in set (0.00 sec) flush status; # first_name字段是索引 select * from employees where first_name = 'Kyoichi'; SHOW SESSION STATUS LIKE "Handler%"; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 2 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 251 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+-------+ flush status; # 带有limit子句的情况 select * from employees where first_name = 'Kyoichi' limit 10; SHOW SESSION STATUS LIKE "Handler%"; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Handler_commit | 1 | | Handler_delete | 0 | | Handler_discover | 0 | | Handler_external_lock | 2 | | Handler_mrr_init | 0 | | Handler_prepare | 0 | | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 9 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | | Handler_rollback | 0 | | Handler_savepoint | 0 | | Handler_savepoint_rollback | 0 | | Handler_update | 0 | | Handler_write | 0 | +----------------------------+-------+ 18 rows in set (0.00 sec)
默认禁用,但它是会话级别的参数。
set profiling=1 ,然后在服务器上直送所有的语句,都会测量其耗费的时间和其他一些查询执行状态变更相关的数据。
当一条查询提交给服务器时,此工具会记录剖析信息到一张临时表,并给查询赋一个从1开始的整数标识符。
set profiling=1; select * from t_Order; select * from t_Product; show profiles; +----------+------------+-------------------------+ | Query_ID | Duration | Query | +----------+------------+-------------------------+ | 1 | 9.75e-05 | SHOW WARNINGS | | 2 | 0.00052075 | select * from t_order | | 3 | 0.000511 | select * from t_product | | 4 | 5.3e-05 | SHOW WARNINGS | +----------+------------+-------------------------+ show profile for query 3; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 0.000065 | | checking permissions | 0.000009 | | Opening tables | 0.000142 | | init | 0.000022 | | System lock | 0.000010 | | optimizing | 0.000008 | | statistics | 0.000013 | | preparing | 0.000012 | | executing | 0.000007 | | Sending data | 0.000154 | | end | 0.000010 | | query end | 0.000011 | | closing tables | 0.000010 | | freeing items | 0.000016 | | cleaning up | 0.000012 | +----------------------+----------+
这个指标是非常具有迷惑性的,它不是单纯指mysql服务器往客户端发送数据,而应该理解为”读取、筛选、聚合并发送数据“。
这个状态出现在sql即将进行大量的磁盘读取的时候。
慢查询一般这个指标都比较高,这个状态如果耗时长,代表的原因非常多,单看该指标很难分析出东西,需要视具体情况而定:
stackOverflow的案例:
其他指标请参考
mysql5:https://dev.mysql.com/doc/refman/5.7/en/general-thread-states.html
mysql8:https://dev.mysql.com/doc/refman/8.0/en/general-thread-states.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。