如何彻底了解MySQL查询优化分析,看了这篇就够了


如何彻底了解MySQL查询优化分析,看了这篇就够了

文章插图
 
手把手教你MySQL查询优化分析前言
MySQL是关系性数据库中的一种,查询功能强,数据一致性高,数据安全性高,支持二级索引 。但性能方面稍逊于非关系性数据库,特别是百万级别以上的数据,很容易出现查询慢的现象 。这时候需要分析查询慢的原因,一般情况下是程序员sql写的烂,或者是没有键索引,或者是索引失效等原因导致的 。
这时候MySQL 提供的 EXPLAIN 命令就尤其重要, 它可以对 SELECT 语句进行分析, 并输出 SELECT执行的详细信息, 以供开发人员针对性优化.
而且就在查询语句前加上 Explain 就成:
准备
首先需要建立两个测试用表及数据:
EXPLAIN 输出格式
EXPLAIN 命令的输出内容大致如下:
各列的含义如下:
  • id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
  • select_type: SELECT 查询的类型.
  • table: 查询的是哪个表
  • partitions: 匹配的分区
  • type: join 类型
  • possible_keys: 此次查询中可能选用的索引
  • key: 此次查询中确切使用到的索引.
  • ref: 哪个字段或常数与 key 一起被使用
  • rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
  • filtered: 表示此查询条件所过滤的数据的百分比
  • extra: 额外的信息
接下来我们来重点看一下比较重要的几个字段.
select_type
  • SIMPLE —— 简单的select 查询,查询中不包含子查询或者UNION
  • PRIMARY —— 查询中若包含任何复杂的子查询,最外层查询则被标记为primary
  • UNION —— 表示此查询是 UNION 的第二或随后的查询
  • DEPENDENT UNION —— UNION 中的第二个或后面的查询语句, 取决于外面的查询
  • UNION RESULT —— 从UNION表获取结果的select结果
  • DERIVED —— 在from列表中包含的子查询被标记为derived(衍生)MySQL会递归执行这些子查询,把结果放在临时表里 。
  • SUBQUERY —— 在select或where 列表中包含了子查询
  • DEPENDENT SUBQUERY —— 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果.
最常见的查询类别应该是 SIMPLE 了, 比如当我们的查询没有子查询, 也没有 UNION 查询时, 那么通常就是 SIMPLE 类型, 例如:
如果我们使用了 UNION 查询, 那么 EXPLAIN 输出 的结果类似如下:
table
表示查询涉及的表或衍生表
type
type 字段比较重要, 它提供了判断查询是否高效的重要依据依据. 通过 type 字段, 我们判断此次查询是 全表扫描 还是 索引扫描 等.
type 常用类型
type 常用的取值有:
  • system: 表中只有一条数据. 这个类型是特殊的 const 类型.
  • const: 针对主键或唯一索引的等值查询扫描, 最多只返回一行数据. const 查询速度非常快, 因为它仅仅读取一次即可.
    例如下面的这个查询, 它使用了主键索引, 因此 type 就是 const 类型的.
  • eq_ref: 此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较操作通常是 =, 查询效率较高. 例如:
  • ref: 此类型通常出现在多表的 join 查询, 针对于非唯一或非主键索引, 或者是使用了 最左前缀 规则索引的查询.
    例如下面这个例子中, 就使用到了 ref 类型的查询:
  • range: 表示使用索引范围查询, 通过索引字段范围获取表中部分数据记录. 这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中.
    当 type 是 range 时, 那么 EXPLAIN 输出的 ref 字段为 NULL, 并且 key_len 字段是此次查询中使用到的索引的最长的那个.
例如下面的例子就是一个范围查询:
  • index: 表示全索引扫描(full index scan), 和 ALL 类型类似, 只不过 ALL 类型是全表扫描, 而 index 类型则仅仅扫描所有的索引, 而不扫描数据.
    index 类型通常出现在: 所要查询的数据直接在索引树中就可以获取到, 而不需要扫描数据. 当是这种情况时, Extra 字段 会显示 Using index.
例如:
上面的例子中, 我们查询的 name 字段恰好是一个索引, 因此我们直接从索引中获取数据就可以满足查询的需求了, 而不需要查询表中的数据. 因此这样的情况下, type 的值是 index, 并且 Extra 的值是 Using index.