Hello,大家好,我是烤鸭,这几天消失了一下,主要是线上系统出了点小bug和sql性能问题,在努力搬砖,就把之前的设计模式系列放了一下下,正好趁这个复习巩固了一下sql执行计划和sql优化等相关的东西,本篇文章我主要用来学习mysql的执行计划和索引分类,也和大家分享下吧,也请大神们不吝赐教

  先来熟悉一下索引吧。索引是在存储引擎中实现的,不同的存储引擎可能会使用不同索引,Myisam和InnoDB存储引擎只能支持BTREE索引,不能更换,而MEMORY/HEAP存储引擎支持HASH和BTREE索引;

  常用的索引我们分为三大类:包括单列索引(普通索引、唯一索引、主键索引等)、组合索引、全文索引等;

  1、单列索引:一个索引只包含一列,但是一张表中可以有多个单列索引;

    1.1普通索引,没有什么限制,允许在定义索引列中插入空值和重复值,纯粹是为了查询数据更快点;

    1.2唯一索引,索引列中的值必须是唯一的,允许空值;

    1.3主键索引,是一种特殊的唯一索引,不允许有空值;

  2、组合索引:在表中的多个字段组合上创建的索引,只有在查询条件中使用这些字段的左边字段时,索引才会被使用,使用组合索引时候遵循左前缀集合的原则,例如有id、name、age这3个字段构成的组合索引,索引行中就按照id/name/age的顺序存放,索引可以索引下面字段组合(id/name/age)、(id/name)、(id/age)、id,如果要查询的字段构不成索引的最左前缀,那么是不会使用索引的,如(name/age)、age组合就不会使用索引;

  3、全文索引(fulltext索引):mysql5.6之前的版本,只有在Myisam存储引擎上使用,mysql5.6之后的版本innodb和myisam存储引擎均支持全文索引,并且只能在char、varchar、text类型的字段上才能使用全文索引;全文索引主要用来查找文本中的关键字,而不是直接与索引中的值比较,更像是一个搜索引擎,而不是简单地where语句参数的匹配,在数据量较大的时候,先将数据写入到一张没有全文索引表中,再创建fulltext索引的速度,要比先为一张表建立fulltext索引,再将数据写入的速度快很多。

  覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行(它包括在查询里的Select、Join和Where子句用到的所有列)。索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此不必读取整个数据行,索引的叶子节点存储了它们的索引数据,当能通过读取索引就可以得到所需要的数据,那就不需要读取数据行了,一个索引包含了(或者覆盖率)满足查询结果的数据就叫做覆盖索引。

  索引的创建和简单用法参见:

  那么我们怎么知道是否使用了覆盖索引呢?如果使用了覆盖索引,在Extra字段会输出Using index字段,那么我们就可以知道当前查询使用了覆盖索引。

  下面开始学习sql执行计划啦!!!

  我使用的mysql版本是5.6.16-log,建表语句如下:  

CREATE TABLE `actor` (
  `id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `film` (
  `id` int(11) NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `film_actor` (
  `id` int(11) NOT NULL,
  `film_id` int(11) NOT NULL,
  `actor_id` int(11) NOT NULL,
  `remark` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_film_actor_id` (`film_id`,`actor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
09-08 16:07