zoukankan      html  css  js  c++  java
  • MySQL 优化之 EXPLAIN 关键字

    MySQL查询优化之explain的深入解析

    0. 准备

    首先执行如下的 sql 语句:

    CREATE TABLE IF NOT EXISTS `article` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `author_id` int(10) unsigned NOT NULL,
    `category_id` int(10) unsigned NOT NULL,
    `views` int(10) unsigned NOT NULL,
    `comments` int(10) unsigned NOT NULL,
    `title` varbinary(255) NOT NULL,
    `content` text NOT NULL,
    PRIMARY KEY (`id`)
    );
    
    
    INSERT INTO `article`
    (`author_id`, `category_id`, `views`, `comments`, `title`, `content`) VALUES
    (1, 1, 1, 1, '1', '1'),
    (2, 2, 2, 2, '2', '2'),
    (1, 1, 3, 3, '3', '3');

    1. EXPLAIN 关键字

    想要查询 category_id 为 1 且 comments 大于 1 的情况下,views 最多的 article_id。

    语句如下(在传统的查询语句前加上 EXPLAIN 关键字):

    EXPLAIN
    SELECT author_id
    FROM `article`
    WHERE category_id = 1 AND comments > 1
    ORDER BY views DESC
    LIMIT 1;

    给出如下的查询结果:

    id: 1
    select_type: SIMPLE
    table: article
    type: ALL
    possible_keys: NULL
    key: NULL
    key_len: NULL
    ref: NULL
    rows: 3
    Extra: Using where; Using filesort
    1 row in set (0.00 sec)

    2. EXPLAIN 关键字与 MySQL 查询优化器

    MySQL 查询优化器有几个目标,但是其中最主要的目标是尽可能地使用索引,并且使用最严格的索引来消除尽可能多的数据行。

    EXPLAIN 的每个输出行提供一个表的相关信息,并且每个行包括下面的列:

    • id:MySQL Query Optimizer 选定的执行计划中查询的序列号。表示查询中执行 SELECT 子句或操作表的顺序,id 值越大优先级越高,越先被执行。id 相同,执行顺序由上至下。
    • select_type 查询类型
      • SIMPLE:简单的 select 查询,不使用 union 及子查询
      • PRIMARY:最外层的 select 查询
      • UNION:UNION 中的第二个或随后的 select 查询,不 依赖于外部查询的结果集
      • DEPENDENT UNION:UNION 中的第二个或随后的 select 查询,依 赖于外部查询的结果集
      • SUBQUERY:子查询中的第一个 select 查询,不依赖于外 部查询的结果集
      • DEPENDENT SUBQUERY:子查询中的第一个 select 查询,依赖于外部 查询的结果集
      • DERIVED:用于 from 子句里有子查询的情况。 MySQL 会 递归执行这些子查询, 把结果放在临时表里。
      • UNCACHEABLE SUBQUERY:结果集不能被缓存的子查询,必须重新为外 层查询的每一行进行评估。
      • UNCACHEABLE UNION:UNION 中的第二个或随后的 select 查询,属 于不可缓存的子查询
    • table:输出行所引用的表
    • extra:中出现以下 2 项意味着 MYSQL 根本不能使用索引,效率会受到重大影响。应尽可能对此进行优化。
      • Using filesort:表示 MySQL 会对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。MySQL 中无法利用索引完成的排序操作称为“文件排序”
      • Using temporary:表示 MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。

    如果 EXPLAIN 的输出结果中,type 对应的是 ALL,extra 还出现了 Using filesort,都意味着 SQL 语句虽然能够工作,但其实是最坏的,并没有合理使用的 sql 查询语句。

    3. 创建索引

    ALTER TABLE `article` ADD INDEX x ( `category_id` , `comments`, `views` );

    添加 INDEX 索引之后,再次调用 EXPLAIN 语句,可以看到,type 变成了 range,这是可以忍受的。但是 extra 里使用 Using filesort 仍是无法接受的。也即并未使用上面创建的索引。这是因为按照 BTree 索引的工作原理,先排序 category_id,如果遇到相同的 category_id 则再排序 comments,如果遇到相同的 comments 则再排序 views。当 comments 字段在联合索引里处于中间位置时,因comments > 1 条件是一个范围值,MySQL 无法利用索引再对后面的 views 部分进行检索,即 range 类型查询字段后面的索引无效。

    DROP INDEX x ON article;
    ALTER TABLE `article` ADD INDEX y ( `category_id` , `views` ) ;
  • 相关阅读:
    51nod 1122 机器人走方格 V4(矩阵乘法)
    51nod 1092 回文字符串
    51nod 1254 最大子段和 V2(递推)
    容斥原理求gcd为k的数对个数
    51nod 1115 最大M子段和 V3
    51nod 1053 最大M子段和 V2(贪心)
    洛谷P1792 [国家集训队]种树
    洛谷P1484 种树(反悔贪心,双向链表+堆)
    51 nod 1052 最大M子段和
    51 nod 1051 最大子矩阵和
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9421151.html
Copyright © 2011-2022 走看看