文章插图
手把手教你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, 取决于外面的查询. 即子查询依赖于外层查询的结果.
如果我们使用了 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.
- ALL: 表示全表扫描, 这个类型的查询是性能最差的查询之一. 通常来说, 我们的查询不应该出现 ALL 类型的查询, 因为这样的查询在数据量大的情况下, 对数据库的性能是巨大的灾难. 如一个查询是 ALL 类型查询, 那么一般来说可以对相应的字段添加索引来避免.
推荐阅读
- 如何用Python爬取网易云两百万热歌
- 茶叶品牌店长如何检测门店客户忠诚度
- 如何去除 WPS Office "热点弹窗"及"广告推送"?
- 如何腌肉更嫩 怎么腌肉又嫩又滑
- 打美白针有哪些危害,美白针你了解多少?
- 历史 赵云是怎么死的(赵云如何死去的?)
- 如何消除额头皱纹呢?
- 如何祛痘印才是有效的?
- 智能饮水机应该如何选购
- 淘金币如何兑换商品 淘宝淘金币活动