查看SQL执行频率
MySQL 客户端连接成功后,通过show[session|global] status 命令可以提供服务器状态信息。通过如下指令可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次:
|
|
结果如下:
|
|
查询慢日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。MySQL的慢查询日志默认没有开启,执行一下SQL查看慢日志开启状态:
1SHOW VARIABLES LIKE 'slow_query_log';
需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
|
|
重启MySQL服务,本机环境为win10的WSL2,直接执行以下命令:
|
|
profile详情
show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪去了。通过have_profiling参数,能够看到当前MySQL是否支持profile操作:
|
|
默认profiling是关闭的,可以通过set语句在session/global级别开启profiling:
|
|
执行完查询语句后再执行show profiles,结果如下:
|
|
explain 执行计划
EXPLAIN 或者 DESC 命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。语法如下:
|
|
结果如下:
|
|
EXPLAIN 输出列如下:
| Column | JSON Name | Meaning |
|---|---|---|
| id | select_id |
SELECT 标识符 |
| select_type | None |
SELECT 类型 |
| table | table_name |
输出行table |
| partitions | partitions |
匹配的分区 |
| type | access_type |
连接类型 |
| possible_keys | possible_keys |
可能的索引选择 |
| key | key |
实际选择的索引 |
| key_len | key_length |
所选键的长度 |
| ref | ref |
与索引比较的列 |
| rows | rows |
估计要检查的行 |
| filtered | filtered |
按table条件过滤的行百分比 |
| Extra | None |
扩展信息 |
😀 Note 详细解释可参考 [官方文档]
-
id行标识,如果没有子查询或者联合查询,这个值是1,id列值越大越先执行,如果一样大,那么就从上往下依次执行 -
select_type查询的类型,可以是下表的任何一种类型select_type 类型说明 SIMPLE简单 SELECT(不使用UNION或子查询)PROMARY最外层的 SELECTUNIONUNION中第二个或之后的SELECT语句DEPENDENT UNIONUNION中第二个或之后的SELECT语句取决于外面的查询UNION RESULTUNION的结果SUBQUERY子查询中的第一个 SELECTDEPENDENT SUBQUERY子查询中的第一个 SELECT,取决于外面的查询DERIVED衍生表(FROM自居中的子查询) MATERIALIZED物化子查询 UNCACHEABLE SUBQUERY结果集无法缓存的子查询,必须重新评估外部查询的每一行 UNCACHEABLE UNIONUNION中第二个或之后的SELECT,属于无法缓存的子查询
⭐
DEPENDENT意味着使用了关联子查询
-
table:输出行所引用表的名称,也可以是以下值之一:- <unionM,N>: 引用id为M和N UNION之后的结果。
: 引用id为N的结果派生出的表,派生表可以是一个结果集,例如派生自FROM中子查询的结果。 : 引用id为N的子查询结果物化得到的表,即生成一个临时表保存子查询的结果。
-
partitions:v5.7之前该项是explain partitions显示的选项,v5.7之后成为了默认选项,该列显示的为分区表中的分区情况,非分区表该字段为空(null)。 -
type( 重要 ):连接类型
-
system表中只有一行数据或者是空表,这是const类型的一个特例,且只能用于MyISAM和Memory表,如果是InnoDB引擎表,type列在这个情况通常都是all或者index -
const最多只有一行记录匹配。当联合主键或唯一索引的所有字段跟常量值比较时,join类型为const。其他数据库也叫做唯一索引扫描 -
eq_ref多表join时,对于来自前面表的每一行,在当前表中只能找到一行,这可能是除了system和const之外最好的类型,当主键或唯一非NULL索引的所有字段都被当做join连接时会出现此类型。eq_ref可用于使用’=‘操作符作比较的索引列,比较的值可以是常量,也可以是使用此表之前读取的表的列表达式。 -
ref对于来自前面表的每一行,在此表的索引中可以匹配到多行,若连接只用到索引的最左前缀或索引不是主键或唯一索引时,使用ref类型(也就是说,此类型能够匹配到多行连接)。ref可用于使用=或<=>操作符作比较的索引列。 -
fulltext用于全文索引的时候是这个类型,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在,mysql不管代价,优先选择使用全文索引 -
ref_or_null类似于ref类型,只是增加了null值得比较,实际用的不多 -
index_merge此类型表示查询使用两个以上索引,最后取交集或者并集,常见and,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range。 -
unique_subquery用于WHERE中的IN形式子查询,子查询返回不重复值唯一值,可以完全替换子查询,效率更高。 该类型替换了下面形式的IN子查询的ref:value IN (select primary_key FROM single_table WHERE some_expr) -
index_subquery该连接类型类似于unique_subquery。适用于非唯一索引,可以返回重复值 -
range索引范围查询,常见于使用=<>>>=<<=IS NULL<=>BETWEENIN或者LIKE等运算符的查询中。 -
index索引全表扫描,把索引从头到尾扫一遍。这里包含两种情况: 一种是查询使用了覆盖索引,那么它只需要扫描索引就可以获得数据,这个效率要比全表扫描要快,因为索引通常比数据表小,而且还能避免二次查询。在extra中显示Using index,反之,如果在索引上进行全表扫描,没有Using index的提示。 -
all全表扫描,性能较差
-
-
possible_keys:查询可能用到的索引,如果此列是
NULL,则没有用到索引。 -
key:表示MySQL实际决定使用的索引,如果MySQL决定使用其中一个
possible_keys索引来查找行,则该索引将作为键值列出。 -
key_length:查询用到的索引长度(字节), 如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,用多少算多少。例如组合索引为
idx_username_create_time,当查询语句为select * from user where username='qqq'时,只用到了username字段,那么key_len只会计算username字段占用的字节数,假如username字段类型为varchar(50)NOT NULL,字符编码为utf8mb3(utf8编码一个字符占用3个字节,gbk编码一个字符占2字节),记录字符串长度占用2字节,记录字段不为空占用1字节(若没有NOT NULL限制则不占用这1个字节)那么key_len为 50 * 3 + 2 + 1 = 153字节 -
ref:如果使用的是常数等值查询,这里会显示
const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列表发生了内部隐式转换,这里可能显示为func。 -
rows( 重要 ):
rows也是一个重要的字段,这是MySQL估算的需要扫描的行数(不是精确值)。这个值非常直观显示SQL的效率好坏,原则上rows越少越好。 -
filtered:该字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。
-
Extra( 重要 ):
EXPLAIN中很多额外的信息会在Extra字段显示,常见的有以下:distinct: 在select部分使用了distinct关键字Using filesort: 当Extra中有Using filesort时,表示MySQL需额外的排序操作,不能通过索引顺序到达排序效果,一般有Using filesort都建议优化去掉,因为这样的查询CPU资源消耗较大。Using index: “覆盖索引扫描”,表示查询在索引树种就可查找所需数据,不用扫描表数据文件,往往说明性能不错。Using temporary: 查询有使用临时表,一般出现于排序,分组和多表join的情况,查询效率不高,建议优化。