从原理到优化,深刻浅出数据库索引

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
数据库查询是数据库的最主要功能之一,咱们都但愿查询数据的速度能尽量的快,所以数据库系统的设计者会从查询算法的角度进行优化,这篇文章对索引作一个系统的梳理,但愿对你们有帮助。html

1、MySQL有哪些索引类型

索引的分类能够从多个角度进行,下面分别从数据结构,物理存储和业务逻辑三个维度进行划分。node

一、从数据结构角度

(1)B+树索引(O(log(n)))

关于B+树索引,后面会深刻解析mysql

(2)hash索引

  • 仅仅能知足"=","IN"和"<=>"查询,不能使用范围查询
  • 其检索效率很是高,索引的检索能够一次定位,不像B-Tree 索引须要从根节点到枝节点,最后才能访问到页节点这样屡次的IO访问,因此 Hash 索引的查询效率要远高于 B-Tree 索引
  • 只有Memory存储引擎显示支持hash索引

(3)FULLTEXT索引

如今MyISAM和InnoDB引擎都支持了算法

(4)R-Tree索引

用于对GIS数据类型建立SPATIAL索引sql

二、从物理存储角度

(1)汇集索引(clustered index)

  • 正文内容按照一个特定维度排序存储,这个特定的维度就是汇集索引;
  • Innodb存储引擎中行记录就是按照汇集索引维度顺序存储的,Innodb的表也称为索引表;由于行记录只能按照一个维度进行排序,因此一张表只能有一个汇集索引。

(2)非汇集索引(non-clustered index)

  • 索引是经过二叉树的数据结构来描述的,咱们能够这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。数据库

  • 非汇集索引索引项顺序存储,但索引项对应的内容倒是随机存储的;服务器

举个例子说明下:数据结构

create table student (
`id` INT UNSIGNED AUTO_INCREMENT,
`name` VARCHAR(255),
PRIMARY KEY(`id`),
KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

该表中主键id是该表的汇集索引、name为非汇集索引;表中的每行数据都是按照汇集索引id排序存储的;好比要查找name='Arla'和name='Arle'的两个同窗,他们在name索引表中位置多是相邻的,可是实际存储位置可能差的很远。name索引表节点按照name排序,检索的是每一行数据的主键。汇集索引表按照主键id排序,检索的是每一行数据的真实内容。数据结构和算法

三、从逻辑角度

(1)主键索引

主键索引是一种特殊的惟一索引,不容许有空值性能

(2)普通索引或者单列索引

(3)多列索引(复合索引)

复合索引指多个字段上建立的索引,只有在查询条件中使用了建立索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合

(4)惟一索引或者非惟一索引

(5)空间索引

空间索引是对空间数据类型的字段创建的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。

MYSQL使用SPATIAL关键字进行扩展,使得可以用于建立正规索引类型的语法建立空间索引。建立空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MYISAM的表中建立.

2、索引建立方式

CREATE TABLE table_name[col_name data type]
[unique|fulltext|spatial][index|key][index_name](col_name[length])[asc|desc]
  • unique|fulltext|spatial为可选参数,分别表示惟一索引、全文索引和空间索引;
  • index和key为同义词,二者做用相同,用来指定建立索引
  • col_name为须要建立索引的字段列,该列必须从数据表中该定义的多个列中选择;
  • index_name指定索引的名称,为可选参数,若是不指定,MYSQL默认col_name为索引值;length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度;
  • asc或desc指定升序或降序的索引值存储

一、建立表时创建索引

(1)建立普通索引

create table table_name(
    id int(11),
    name varchar(20),
    sex boolean,
    INDEX(id)
);

查看表结构

show create table table_name;
可使 EXPLAIN 语句查看索引是否被使用

explain select * from table_name where id = 1\G

(2)建立惟一索引

create table index2(
    id int unique,
    name varchar(20),
    unique INDEX index_2(id asc)
);

(3)建立全文索引

全文索引只能在char,varchar或者text 类型的字段上。并且,只有MyISAM 储存引擎支持全文索引。

create table idnex3(
    id int,
    info varchar(20),
    FULLTEXT INDEX index3_info(info)
)ENGINE=MyISAM;

(4)建立单列索引

create table index4(
    id int,
    subject varchar(255),
    index index4_st(subject(10))
);

这里须要注意的,subject 的长度为255,可是index4_st索引只有10。这样作的目的仍是为了提升查询速度。对于字符型的数据,能够不用查询所有信息,只查询其前面的若干字符信息。

(5)建立多列索引

create table index5(
    id int,
    name varchar(20),
    sex char(4),
    index index5_ns(name.sex)
);

这是咱们能够看到,name 和sex字段上已经建立了index_ns索引。

二、在已经存在的表中建立索引

(1)建立普通索引

在example0() 表中的id 建立名为index7_id 的索引。

create index index7_id on example0(id);

(2)建立惟一索引

create UNIQUE index index_name on table_name(name);

(3)建立全文索引

create FULLTEXT index index_name on table_name(info);

(4)建立单列索引

create INDEX index_name ON table_name(name(10));

(5)建立多列索引

create INDEX index_name ON table_name(name,sex);

三、用alter table 语句来建立索引

(1)建立普通索引

在name字段上建立名为indx_name 的索引

alter table table_name ADD INDEX index_name(name(20));

(2)建立惟一性索引

alter table table_name ADD UNIQUE INDEX index_name(id);

(3)建立全文索引

alter table table_name ADD FULLTEXT INDEX index_name(info);

(4)建立单列索引

alter table table_name ADD INDEX index_name(name(4));

(5)建立多列索引

alter tabel table_name ADD INDEX index_name(name.sex);

四、删除索引

DROP INDEX index_name ON table_name;

3、索引树是如何维护的

目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree做为索引结构,那么索引树是如何维护的?

一、查找结构进化史

查找是数据结构和算法中一个很是重要的概念。

  • 线性查找:一个个找;实现简单;太慢
  • 二分查找:有序;简单;要求是有序的,插入特别慢
  • HASH查找:查询快;占用空间;不太适合存储大规模数据
  • 二叉查找树:插入和查询很快(log(n));没法存大规模数据,复杂度退化
  • 平衡树:解决 BST 退化问题,树是平衡的;节点很是多的时候,依然树高很高
  • 多路查找树:一个父亲多个孩子节点(度);节点过多树高不会特别深
  • 多路平衡查找树:B-Tree

二、B-Tree

B-Tree是一种多路搜索树(并非二叉的):

  1. 定义任意非叶子结点最多只有M个儿子;且M>2;
  2. 根结点的儿子数为[2, M];
  3. 除根结点之外的非叶子结点的儿子数为[M/2, M];
  4. 每一个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
  5. 非叶子结点的关键字个数=指向儿子的指针个数-1;
  6. 非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
  7. 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的
    子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;
  8. 全部叶子结点位于同一层;
  9. 每一个k对应一个data。
    如:(M=3)至关于一个2–3树,2–3树是一个这样的一棵树, 它的每一个节点要么有2个孩子和1个数据元素,要么有3个孩子和2个数据元素,叶子节点没有孩子,而且有1个或2个数据元素。

B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,若是命中则结束,不然进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为空,或已是叶子结点;B-Tree上查找算法的伪代码以下:

BTree_Search(node, key) { if(node == null) return null; foreach(node.key) { if(node.key[i] == key) return node.data[i]; if(node.key[i] > key) return BTree_Search(point[i]->node); } return BTree_Search(point[i+1]->node); } data = BTree_Search(root, my_key);

(1)B-树的特性

  1. 关键字集合分布在整颗树中;
  2. 任何一个关键字出现且只出如今一个结点中;
  3. 搜索有可能在非叶子结点结束;
  4. 其搜索性能等价于在关键字全集内作一次二分查找;
  5. 自动层次控制;

(2)B-树的自控制

B树中每个内部节点会包含必定数量的键值。一般,键值的数量被选定在d和2d之间。在实际中,键值占用了节点中大部分的空间。因数2将保证节点能够被拆分或组合。若是一个内部节点有2d个键值,那么添加一个键值给此节点的过程,将会拆分2d键值为2个d键值的节点,并把此键值添加给父节点。每个拆分的节点须要最小数目的键值。类似地,若是一个内部节点和他的邻居二者都有d个键值,那么将经过它与邻居的合并来删除一个键值。删除此键值将致使此节点拥有d-1个键值;与邻居的合并则加上d个键值,再加上从邻居节点的父节点移来的一个键值。结果为彻底填充的2d个键值。

(3)B-树的构造过程

下面是往B树中依次插入

6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

三、B+Tree

B-Tree有许多变种,其中最多见的是B+Tree,MySQL就广泛使用B+Tree实现其索引结构。
与B-Tree相比,B+Tree有如下不一样点:

  1. 非叶子结点的子树指针与关键字个数相同;
  2. 非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);
  3. 为全部叶子结点增长一个链指针;
  4. 全部关键字都在叶子结点出现;
  5. 内节点不存储data,只存储key
    如:(M=3)

B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树能够在非叶子结点命中),其性能也等价于在关键字全集作一次二分查找;

(1)B+的特性

  1. 全部关键字都出如今叶子结点的链表中(稠密索引),且链表中的关键字刚好是有序的;
  2. 不可能在非叶子结点命中;
  3. 非叶子结点至关因而叶子结点的索引(稀疏索引),叶子结点至关因而存储(关键字)数据的数据层;
  4. 更适合文件索引系统;

(2)B+树的构造过程

下面是往B+树中依次插入

6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

三、索引的物理存储

通常来讲,索引自己也很大,不可能所有存储在内存中,所以索引每每以索引文件的形式存储的磁盘上。

这样的话,索引查找过程当中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,因此评价一个数据结构做为索引的优劣最重要的指标就是在查找过程当中磁盘I/O操做次数的渐进复杂度。换句话说,索引的结构组织要尽可能减小查找过程当中磁盘I/O的存取次数。

假如每一个盘块能够正好存放一个B树的结点(正好存放2个文件名)。那么一个BTNODE结点就表明一个盘块,而子树指针就是存放另一个盘块的地址。

(1)模拟B+树查找过程

下面,我们来模拟下查找文件29的过程:

  1. 根据根结点指针找到文件目录的根磁盘块1,将其中的信息导入内存。【磁盘IO操做 1次】
  2. 此时内存中有两个文件名1七、35和三个存储其余磁盘页面地址的数据。根据算法咱们发现:17<29<35,所以咱们找到指针p2。
  3. 根据p2指针,咱们定位到磁盘块3,并将其中的信息导入内存。【磁盘IO操做 2次】
  4. 此时内存中有两个文件名26,30和三个存储其余磁盘页面地址的数据。根据算法咱们发现:26<29<30,所以咱们找到指针p2。
  5. 根据p2指针,咱们定位到磁盘块8,并将其中的信息导入内存。【磁盘IO操做 3次】
  6. 此时内存中有两个文件名28,29。根据算法咱们查找到文件名29,并定位了该文件内存的磁盘地址。
    分析上面的过程,发现须要3次磁盘IO操做和3次内存查找操做。关于内存中的文件名查找,因为是一个有序表结构,能够利用折半查找提升效率。至于IO操做是影响整个B树查找效率的决定因素。
    固然,若是咱们使用平衡二叉树的磁盘存储结构来进行查找,磁盘4次,最多5次,并且文件越多,B树比平衡二叉树所用的磁盘IO操做次数将越少,效率也越高。

四、B+tree的优势

(1)B+-tree的磁盘读写代价更低

B+-tree的内部结点并无指向关键字具体信息的指针。所以其内部结点相对B 树更小。若是把全部同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来讲IO读写次数也就下降了。
举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点须要2个盘快。而B+
树内部结点只须要1个盘快。当须要把内部结点读入内存中的时候,B 树就比B+树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。

(2)B+-tree的查询效率更加稳定

因为非终结点并非最终指向文件内容的结点,而只是叶子结点中关键字的索引。因此任何关键字的查找必须走一条从根结点到叶子结点的路。全部关键字查询的路径长度相同,致使每个数据的查询效率至关。

4、索引建立有哪些原则

索引查询是数据库中重要的记录查询方法,要不要进入索引以及在那些字段上创建索引都要和实际数据库系统的查询要求结合来考虑,下面给出实际中的一些通用的原则:

  1. 在常常用做过滤器的字段上创建索引;
  2. 在SQL语句中常常进行GROUP BY、ORDER BY的字段上创建索引;
  3. 在不一样值较少的字段上没必要要创建索引,如性别字段;
  4. 对于常常存取的列避免创建索引;
  5. 用于联接的列(主健/外健)上创建索引;
  6. 在常常存取的多个列上创建复合索引,但要注意复合索引的创建顺序要按照使用的频度来肯定;
  7. 缺省状况下创建的是非簇集索引,但在如下状况下最好考虑簇集索引,如:含有有限数目(不是不多)惟一的列;进行大范围的查询;充分的利用索引能够减小表扫描I/0的次数,有效的避免对整表的搜索。
  8. 常常用在WHERE子句中的数据列;
  9. 常常出如今关键字order by、group by、distinct后面的字段,创建索引。若是创建的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致,不然索引不会被使用;
  10. 对于那些查询中不多涉及的列,重复值比较多的列不要创建索引;
  11. 对于定义为text、image和bit的数据类型的列不要创建索引;
  12. 对于常常存取的列避免创建索引;
  13. 限制表上的索引数目。对一个存在大量更新操做的表,所建索引的数目通常不要超过3个,最多不要超过5个。索引虽然说提升了访问速度,但太多索引会影响数据的更新操做。
  14. 对复合索引,按照字段在查询条件中出现的频度创建索引。在复合索引中,记录首先按照第一个字段排序。对于在第一个字段上取值相同的记录,系统再按照第二个字段的取值排序,以此类推。所以只有复合索引的第一个字段出如今查询条件中,该索引才可能被使用,所以将应用频度高的字段,放置在复合索引的前面,会使系统最大可能地使用此索引,发挥索引的做用。

一、组合多个索引

一个单独的索引扫描只能用于这样的条件子句:使用被索引字段和索引操做符类中的操做符, 而且这些条件以AND链接。

假设在(a, b)上有一个索引, 那么相似WHERE a = 5 AND b = 6的条件可使用索引,可是像WHERE a = 5 OR b = 6的条件就不能直接使用索引。

一个相似WHERE x =42 OR x = 47 OR x = 53 OR x = 99 这样的查询能够分解成四个在x上的独立扫描,每一个扫描使用一个条件, 最后将这些扫描的结果OR 在一块儿,生成最终结果。

另一个例子是,若是咱们在x 和y上有独立的索引,一个相似WHERE x = 5 AND y = 6 这样的查询能够分解为几个使用独立索引的子句,而后把这几个结果AND 在一块儿,生成最终结果。

5、索引失效有哪几种状况

  1. 若是条件中有or,即便其中有条件带索引也不会使用(这也是为何尽可能少用or的缘由)
  2. 对于多列索引,不是使用的第一部分(第一个),则不会使用索引
  3. like查询是以%开头
  4. 若是列类型是字符串,那必定要在条件中将数据使用引号引用起来,不然不使用索引
  5. 若是mysql估计使用全表扫描要比使用索引快,则不使用索引

一、联合索引失效的条件

联合索引又叫复合索引。两个或更多个列上的索引被称做复合索引。

对于复合索引:Mysql从左到右的使用索引中的字段,一个查询能够只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 能够支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

因此说建立复合索引时,应该仔细考虑列的顺序。对索引中的全部列执行搜索或仅对前几列执行搜索时,复合索引很是有用;仅对后面的任意列执行搜索时,复合索引则没有用处。

6、如何查看索引的使用状况

这里记录两种方式,分别是

一、使用Handler_read查看索引的使用状况

show status like ‘Handler_read%';

你们能够注意:

  • handler_read_key:这个值越高越好,越高表示使用索引查询到的次数
  • handler_read_rnd_next:这个值越高,说明查询低效
+-----------------------+--------------+
| Variable_name         | Value        |
+-----------------------+--------------+
| Handler_read_first    | 153      |
| Handler_read_key      | 364   |
| Handler_read_next     | 425    |
| Handler_read_prev     | 598     |
| Handler_read_rnd      | 605     |
| Handler_read_rnd_next | 860571 |
+-----------------------+--------------+
6 rows in set (0.00 sec)
————————————————

分析这几个值,咱们能够查看当前索引的使用状况:

  • Handler_read_first:索引中第一条被读的次数。若是较高,它表示服务器正执行大量全索引扫描;例如,SELECT col1 FROM foo,假定col1有索引(这个值越低越好)。
  • Handler_read_key:若是索引正在工做,这个值表明一个行被索引值读的次数,若是值越低,表示索引获得的性能改善不高,由于索引不常用(这个值越高越好)。
  • Handler_read_next :按照键顺序读下一行的请求数。若是你用范围约束或若是执行索引扫描来查询索引列,该值增长。
  • Handler_read_prev:按照键顺序读前一行的请求数。该读方法主要用于优化ORDER BY ... DESC。
  • Handler_read_rnd :根据固定位置读一行的请求数。若是你正执行大量查询并须要对结果进行排序该值较高。你可能使用了大量须要MySQL扫描整个表的查询或你的链接没有正确使用键。这个值较高,意味着运行效率低,应该创建索引来补救。
  • Handler_read_rnd_next:在数据文件中读下一行的请求数。若是你正进行大量的表扫描,该值较高。一般说明你的表索引不正确或写入的查询没有利用索引。

二、在sys库中查看没用的索引

查询 schema_unused_indexes库。

root@localhost [sys]>select * from schema_unused_indexes;
+-------------------+-------------+------------+
| object_schema     | object_name | index_name |
+-------------------+-------------+------------+
| sysbench_testdata | sbtest1     | k_1        |
| sysbench_testdata | sbtest10    | k_10       |
| sysbench_testdata | sbtest3     | k_3        |
| sysbench_testdata | sbtest4     | k_4        |
| sysbench_testdata | sbtest5     | k_5        |
| sysbench_testdata | sbtest6     | k_6        |
| sysbench_testdata | sbtest7     | k_7        |
| sysbench_testdata | sbtest8     | k_8        |
| sysbench_testdata | sbtest9     | k_9        |
+-------------------+-------------+------------+
9 rows in set (0.00 sec)

7、EXPLAIN解释命令查看索引是否生效

explain显示了mysql如何使用索引来处理select语句以及链接表。能够帮助选择更好的索引和写出更优化的查询语句。

一、一个实际例子

新建一张表,

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`)
);

执行查询,

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

响应数据以下,

*************************** 1. row ***************************
           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)

type 是 ALL,即最坏的状况。Extra 里还出现了 Using filesort,也是最坏的状况。

二、EXPLAIN列的解释:

  • table:显示这一行的数据是关于哪张表的
  • type:这是重要的列,显示链接使用了何种类型。从最好到最差的链接类型为const、eq_reg、ref、range、indexhe和ALL
  • possible_keys:显示可能应用在这张表中的索引。若是为空,没有可能的索引。能够为相关的域从WHERE语句中选择一个合适的语句
  • key: 实际使用的索引。若是为NULL,则没有使用索引。不多的状况下,MYSQL会选择优化不足的索引。这种状况下,能够在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
  • key_len:使用的索引的长度。在不损失精确性的状况下,长度越短越好
  • ref:显示索引的哪一列被使用了,若是可能的话,是一个常数
  • rows:MYSQL认为必须检查的用来返回请求数据的行数
  • Extra:关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里能够看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢

三、type返回结果的解释

MySQL 在表里找到所需行的方式。包括(由左至右,由最差到最好):
| All | index | range | ref | eq_ref | const,system | null |

  • system 表只有一行:system表。这是const链接类型的特殊状况
  • const:表中的一个记录的最大值可以匹配这个查询(索引能够是主键或唯一索引)。由于只有一行,这个值实际就是常数,由于MYSQL先读这个值而后把它当作常数来对待
  • eq_ref:在链接中,MYSQL在查询时,从前面的表中,对每个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或唯一键的所有时使用
  • ref:这个链接类型只有在查询使用了不是唯一或主键的键或者是这些类型的部分(好比,利用最左边前缀)时发生。对于以前的表的每个行联合,所有记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好
  • range:这个链接类型使用索引返回一个范围中的行,好比使用>或<查找东西时发生的状况
  • index: 这个链接类型对前面的表中的每个记录联合进行彻底扫描(比ALL更好,由于索引通常小于表数据)
  • ALL:这个链接类型对于前面的每个记录联合进行彻底扫描,这通常比较糟糕,应该尽可能避免

四、extra列返回的描述的意义

  • Distinct:一旦MYSQL找到了与行相联合匹配的行,就再也不搜索了
  • Not exists: MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就再也不搜索了
  • Range checked for each Record(index map:#):没有找到理想的索引,所以对于从前面表中来的每个行组合,MYSQL检查使用哪一个索引,并用它来从表中返回行。这是使用索引的最慢的链接之一
  • Using filesort: 看到这个的时候,查询就须要优化了。MYSQL须要进行额外的步骤来发现如何对返回的行排序。它根据链接类型以及存储排序键值和匹配条件的所有行的行指针来排序所有行
  • Using index: 列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的所有的请求列都是同一个索引的部分的时候
  • Using temporary 看到这个的时候,查询须要优化了。这里,MYSQL须要建立一个临时表来存储结果,这一般发生在对不一样的列集进行ORDER BY上,而不是GROUP BY上
  • Using where 使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。若是不想返回表中的所有行,而且链接类型ALL或index,这就会发生,或者是查询有问题不一样链接类型的解释(按照效率高低的顺序排序)

参考文档

最官方的 mysql explain type 字段解读
MySQL汇集索引和非汇集索引

相关文章
相关标签/搜索