MySQL 性能优化工具 EXPLAIN (菜鸟的笔记)

本文很多我自己也是有点懵,只能不断学习去完善本文,如果有错误,或者建议欢迎大佬批评指正。

        做优化的先决条件是明白这个语句发生了什么,当我们遇到一个慢查询时,肯定不能想当然的去处理,明白这个SQL到底经历了什么才是优化的第一步。

        让我们请出今天伟大的主角 EXPLAIN 工具, 它可以模拟优化器执行SQL 语句, 进而分析这段SQL

        干说也没啥意思 MySQL 启动,创建一个测试库,开始我们的EXPLAIN 之旅 (孩子用的MySQL 8, 可能由于版本的问题一些地方存在不同)

使用方法

        在我们的SQL 之前执行EXPLAIN 关键字, MySQL就会返回这段语句的执行计划信息,而不是执行这段SQL (当然,如果你在FROM 中包含子查询,还是会被执行的,毕竟这个生成的临时表是其他SQL执行的前提)

前置工作

第一个表, 我们无数次在Demo项目中写的学生表

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '学生姓名',
  `enroll_time` datetime(0) NULL DEFAULT NULL COMMENT '入学时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '学生信息表' ROW_FORMAT = Dynamic;

然后是课程表

DROP TABLE IF EXISTS `course`;
CREATE TABLE `course`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '课程名称',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '课程信息表' ROW_FORMAT = Dynamic;

学生课程之间万恶的成绩表

DROP TABLE IF EXISTS `score`;
CREATE TABLE `score`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `course_id` int(0) NULL DEFAULT NULL COMMENT '课程主键',
  `student_id` int(0) NULL DEFAULT NULL COMMENT '学生主键',
  `score` decimal(4, 1) NULL DEFAULT NULL COMMENT '成绩',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `course_id`(`course_id`, `student_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

然后加一点测试数据

INSERT INTO 
	student(`name`, enroll_time) 
VALUES 
	('a', '2024-09-12 14:10:43'), 
	('b', '2024-09-11 14:10:43'),
	('c', '2024-09-10 14:10:43');
INSERT INTO 
	course(`name`)
VALUES 
	('计算机基础'), ('计算机网络')
INSERT INTO 
	score(course_id, student_id, score)
VALUES 
	(1,1,99.5),
	(1,2,100),
	(2, 1, 60)

启动

难得有了新玩具孩子先玩一会哈 。。。。

EXPLAIN SELECT * FROM student;   -- 线上环境别用 * 容易挨打, 至于为什么我们后面会说

emm...

EXPLAIN SELECT * FROM student LEFT JOIN score ON student.id = score.student_id;

emm ??? 为啥两条数据 ?? 看来JOIN 会产生多条数据 在测试一下

EXPLAIN SELECT * FROM student 
LEFT JOIN score ON student.id = score.student_id 
LEFT JOIN course ON score.course_id = course.id; -- 多表连接也是挨打的重要一环 。。

看来好像是这样

还有一个配套使用的 SHOW WARNINGS;

他会生成优化器优化后的SQL语句,我们可以大致知道具体做了哪些优化

具体使用方法就是在我们执行EXPLAIN 后立刻执行,当然在Navicat 中我们需要这样

(ps 这里的库命名的有问题哈, 别学我)

执行后查看结果二就可以了

当然如果你要问我Navicat 是啥 ?好玩吗? 贵不贵? 手机上能玩吗?(CSDN 启动 !!)

分析

id

主要是展示SQL的执行顺序:

        一般是有几个SELECT 就有几个id (刚才我们表链接中的id是相同的 emm..)

        Id越大越先执行, Id相同则从上到下 id为NULL 则最后执行

select_type

        见名知意思 查询类型呗

SIMPLE

         简单查询

 EXPLAIN SELECT * FROM student WHERE id = 2;

让我们写一个不简单的呗

ps: 

     孩子实在绕不过衍生表的优化策略,先给关了吧

SET SESSION optimizer_switch='derived_merge=off';
EXPLAIN 
	SELECT score,
	(SELECT count(1) FROM course)
	FROM
	(
		SELECT student.`name`, score.score 
		FROM student LEFT JOIN score ON student.id = score.student_id
	) score_temp WHERE score_temp.name = 'a';

        PS:讲真的我自己都不知道我在些什么,完成为了凑出SELECT_TYPE 我已经是尽力了,有更好的建议请立刻联系我

其中

PRIMARY

代表着改查询为最外层SQL

DERIVED

衍生表呗(百度翻译),我们数据库也没有这张表,MySQL 就会创建一个临时表(衍生表)而且这个查询的执行顺序较高,在FROM后面的子查询,

SUBQUERY

子查询呗, emm.. 在SELECT 后面

再来一个

EXPLAIN
	SELECT id FROM course
	UNION
	SELECT id FROM student

emm...

EXPLAIN
	SELECT id FROM course
	UNION ALL
	SELECT id FROM student

依稀记得,当时刚毕业,背八股, UNION ALL 要比 UNION 少一次查询 没想到在这里证实了

那 UNION 和 UNION RESULT 的意思就很明显了

UNION

在 union 中的第二个和随后的 select

table

见名知意, 查询对应的表呗,

当然存在 <derivedN> 这种 其中N 代表衍生表的Id, 表示当前查询依赖于某个Id 为n 的查询

<union 1, 2> 表示一个UNION RESULT的查询依赖于 id 为 1, 2的查询结果

partitions

        这个字段在分区的时候会有用,至于现在吗,先当成不存在吧(手动狗头)。。。

type

        emm。。。 感觉到一股强大的气息, emm

这个作为本文的重点其语义是描述MySQL 是如何寻找查询中的行数据,听起来好。。。

但是如果我们把他的可能的值拿出来,就显得没那么抽象了

其中:

system > const > eq_ref > ref > range > index > all

ps: 当然具体的业务场景具体分析,ALL的性能不一定很差, system 的性能一定很好 (手动狗头)

ps: 其中有一个我们很容易忽略的值 NULL

NULL

看SQL

EXPLAIN SELECT MAX(id) FROM course;

对你没有看错,没有 NULL, 但是并不代表没有有用信息,让我们尝试翻译一下EXTRA中的值

Select tables optimized away -- 选的 表 优化 离开  (选择了一个一个被优化没的表)

        很显然 连表都不用看,直接在优化阶段处理了。这种情况一般出现在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表(像我们用char来写字符串,一般会把字符串的长度存储起来,当你String.length() 时,其实只是把我们维护的变量返回回去)

SYSTEM/CONST

        为什么我要把这个两个放在一起讲嘞?因为这两个比较容易混淆 so

看 SQL

EXPLAIN SELECT * FROM ( SELECT id FROM student WHERE id = 1) temp;

两个都出来了,至于const 我们经常见到,按照主键id查询就可以了

看SQL

EXPLAIN SELECT id FROM course WHERE id = 1;

如果,我是说如果我们的表中只有一条数据 会发生什么?

随便创建一个表,让我们测试一下 (表结构我就不多做赘述了就一个id一个name )

先插入一条数据

看SQL

EXPLAIN SELECT * FROM temp WHERE id = 1;

哎?为啥不是System?? 坏了翻车了, 这个表里面就一条数据啊,

emm。。。

我看到教程上明明说(system是const的特例,表里只有一条元组匹配时为system)

emm.... ,

只有一条 emm... 哎 有了

EXPLAIN SELECT * FROM (SELECT name FROM temp WHERE id = 1) temp

也就是说 system 的出现和具体查询那个字段没有关系, id 可以出现, name 可以出现。

再来一个SQL

EXPLAIN SELECT * FROM (SELECT name FROM temp WHERE name = 'a') temp

明明只有一条记录,但是没有发现, 难道和索引有关,先来一个普通索引

好像也没有出现,那唯一性索引嘞?

出现了, 唯一性索引相比于普通索引只不过多了唯一性约束,让我们的值只会有一个,

一个 ? 一个 !!

明明只有一条记录,但是没有发现,正好侧面证实了 EXPLAIN 不会真的查询,

他只会在语义方面考虑,

也就是说我们要让优化器觉得我们这里只有一条数据, 

如何让优化器觉得我们这里只有一条数据嘞?

  1. LIMIT

  2. 主键

  3. 唯一键

PS: (其实主键也是一种唯一键)

PS: 注意这里也出现了CONST 

现在就剩下一个LIMIT 了 看SQL

EXPLAIN SELECT * FROM (SELECT name FROM student LIMIT 1) temp1

让我们大胆猜测一下

这种情况看来只会出现在按照唯一键查询,=》 CONST;

当数据表被分析认为只有一条数据时 为 =》 SYSTEM

至于论证 SYSTEM 是一种特殊的CONST

emm.. 这个要从语义上来分析了 => const 的语义不就是确定数量的意思吗,一不也是一种常数 (好累,好烦,好饿 如果有个大佬能给我一个更好的解释方案就好了 (手动拜托))

有头有尾, 先把祸害我这么长时间的temp表删掉(叉腰)

(好像忘记点什么,算了不管了,,,, 溜咯)

EQ_REF

emm, 这个好像出现过,在那里嘞??

对~~ 比较靠前的位置里, 我背着我的技术总监偷偷的做了一个多表连接 

EXPLAIN SELECT * FROM student 
LEFT JOIN score ON student.id = score.student_id 
LEFT JOIN course ON score.course_id = course.id; -- 多表连接也是挨打的重要一环 。。

换成两个表链接试试

EXPLAIN SELECT * FROM student LEFT JOIN score ON student.id = score.student_id ;

哎, 咋成了ALL 了, 这不对吧 emm, 让我们换一下位置

EXPLAIN SELECT * FROM score LEFT JOIN  student ON student.id = score.student_id ;

这里我们又不得不涉及到驱动表和被驱动表的概念了 小表驱动大表是我们比较常见的说法,在第一条语句中student 相比于 score 肯定是小表,我们拿出一个student 时 根据我们的查询条件去score表中查询数据,这一次是没有索引的。至于第二次我们先拿出score表,其中的student id正好是我们的主键就可以出现eq_ref了

每日一问:我不是记得score表有索引吗? 

答不出来的自觉回我上一篇博客(记得点个赞哈)

是时候给出结论了

primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。这可能是在 const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。

REF

不eq的ref

emm...

 普通索引秒了,等。。

我么好像在很多地方都出现过这个

看SQL

普通查询:

ps: 给student创建一个name普通索引

EXPLAIN SELECT * FROM student WHERE name = 'a'

最左前缀:

EXPLAIN SELECT * FROM score WHERE course_id = 1

emm 是时候给出结论了

相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行

range

range 我好像在哪里见过这个单词 emm...

(不得不说, 这些参数全是外国佬设计的,多学点英语确实有优势,卑微的小芦同学只能默默的打开翻译软件, 仰天长叹)

范围吗? 范围, emm 不就是 > < 那一套吗? 亮个像吧,小宝贝

EXPLAIN SELECT * FROM score WHERE id < 1;

emm

那普通键嘞

EXPLAIN SELECT * FROM student WHERE name > 'a';

组合索引

EXPLAIN SELECT * FROM score WHERE course_id > 1

当然有个问题然然升起,In 属于范围吗?

看SQL

EXPLAIN SELECT * FROM student WHERE id in (1,2,3)

emm, 属于,emm 为啥??

(这个问题,孩子也不知道,如果有大佬给孩子解释,孩子感激不尽)

又到了给结论的时候了

范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。

INDEX

emm 看名字好像nb哄哄 不知道的以为你是大哥大嘞, 索引, Index, 结果你丫告诉我,你要扫描全部索引(一般是扫描某个二级索引)

EXPLAIN SELECT id,name FROM student;

emm 为啥我不用 * 了 ??

EXPLAIN SELECT * FROM student;

emm, 其实这里有个比较隐秘的知识点

覆盖索引: (具体概念自己查,我也记不住) =>  当我们索引中有我们需要的全部数据时,只需要扫描一次二级索引就可以解决的了(快问快答 二级索引树中有哪些字段 ~~ )

出结论吧:

扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比ALL快一些。

至于为啥比ALL 快, 因为比较小,为啥比较小, 难道比较小就快??

emm.. (手动狗头) 打不出来的自觉 启动CSDN 吧

ALL

见名之一,我甚至不想写SQL了因为这玩意太常见了,就你写了一个查询,还不加索引,一般都是这种情况, 全表扫描呗(聚簇)。

结论:

即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。

possible_keys

possible 可能

key emm 索引,

emm....

这一列显示查询可能使用哪些索引来查找。

ps:

explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。 

如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果。

key

emm... 如果你单独出来,我可能会疑惑,但是你兄弟把你卖了, 想必阁下就是实际使用的索引吧

ps: 

如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。

key_len列

索引的长度?

emm... 先把对照表掏出来

字符串

char(n)和varchar(n),5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节

char(n):如果存汉字长度就是 3n 字节

varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为varchar是变长字符串

数值类型

        tinyint:1字节         bigint:8字节  int:4字节        smallint:2字节

时间类型 

        date:3字节        timestamp:4字节        datetime:8字节

ps: 如果字段允许为 NULL,需要1字节记录是否为 NULL

先拉出几个SQL试验一下

EXPLAIN SELECT id,name FROM student;

看一下我们的索引及字段信息

CREATE TABLE `student` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '学生姓名',
  `enroll_time` datetime DEFAULT NULL COMMENT '入学时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='学生信息表'

通过key 我们知道这里是用到了name索引

具体长度的话 emm.... 为啥长度对应不对?? CSDN 启动!!

utf8: 在MySQL中,utf8编码最大字符长度为3字节。这意味着它支持Unicode中的基本多文种平面(BMP),其字符范围是U+0000至U+FFFF。

utf8mb4:utf8mb4编码最大字符长度为4字节。它是为了专门兼容四字节的Unicode字符而设计的,因此能够支持包括emoji表情、某些不常用的汉字以及任何新增的Unicode字符等。

很明显我们这里用到的是utf8mb4 四个字节 那计算就成了 4 * 25 (name长度) + 1 (name是否为空) + 2 (id长度) = 103 呕吼这样就对了

在我们计算长度时,一定要注意字符编码的问题(依稀记得,我的第一个线上大事故就是因为字符编码引起的,和技术总监劈里啪啦的去找问题,结果。。。) 

这里我们试着把编码集改一下

----------------- 重点---------------------------------
  `name` varchar(25) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '学生姓名',
-----------------结束了-----------------------------------------------

 在执行一次

EXPLAIN SELECT id,name FROM student;

ps: MySQL8 之所以选用utf8mb4 这种编码方式是由于它可以兼容一些特殊字符比如😊 或者特殊字符, utf8mb4 作为 UTF-8的超集则具备了这些能力,在做长度分析的时候记得看一下自己数据库的字符集编码哈。

给总结吧

这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

ref

emm, ref是 引用?? 啥意思??, 但是我记得我们的SQL里面出现过这种类型的字段

EXPLAIN SELECT * FROM score WHERE score.course_id = 1;

const 我知道啊常量 emm

在走一个

EXPLAIN SELECT * FROM  score LEFT JOIN  student ON score.student_id = student.id ;

emm 这里的 test-explain.score.student_id似乎暴露了一切, 库名.表名.字段名 呗  

那答案也呼之欲出了

这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),字段名(例:student.id)

rows

这个,我们出现过很多次了,相信大家也能猜出来, 扫描的行数呗,就比如ALL 那就是rows大约等于表长度, id的话大概为1, 一般索引的话 emm.

不对,我们的EXPLAIN其实有一个默认前提的就是他不会真的去执行,也就说明这些数据都是估算的,至于如何估算的我们以后再讲

给出结果

这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。

filtered 

这个emm, 让我们打开官方文档看看吧

万能宝典

filtered (JSON name: filtered)
The column indicates an estimated percentage of table rows that are filtered by the table condition. The maximum value is 100, which means no filtering of rows occurred. Values decreasing from 100 indicate increasing amounts of filtering. shows the estimated number of rows examined and × shows the number of rows that are joined with the following table. For example, if is 1000 and is 50.00 (50%), the number of rows to be joined with the following table is 1000 × 50% = 500. filteredrowsrowsfilteredrowsfiltered.

emm... 百度翻译启动(哎... 咱们硬着头皮试试呗)

  • The column indicates an estimated percentage of table rows that are filtered by the table condition.
    • 这个 列  表明 一个 估算 百分比 关于 表 rows 他们 过滤 通过 表的条件??
      也就是表明一个 估算值,通过表的判断条件呗
  • The maximum value is 100, which means no filtering of rows occurred.
    • 这个 最大值  是 100 他 意味着 没有 过滤 对于 行 发生 ??
      最大值是100 表明没有进行过滤呗 
  • Values decreasing from 100 indicate increasing amounts of filtering.
    • 值 描述(减少) 从 100 表明 减少 数字 关于 过滤 (啊对 不是描述是减少)
      这个值从一百开始减少表明了被我们过滤掉的数据在增加
  •  shows the estimated number of rows examined and × shows the number of rows that are joined with the following table.
    • 展示 这个 估算的 数字 关于 rows 考试? 和 乘号 这个数字 关于 rows 这个 是 链接 和 接下来的表(我感觉)
      这个是一个行检查的估计值,同时于rows对应的数字相乘代表着与下表的连接行数
  • For example, if is 1000 and is 50.00 (50%), the number of rows to be joined with the following table is 1000 × 50% = 500. 
    • 举个例子, 如果 是 1000 和 50 ,被下表链接的数字就是 1000 * 50%

总结就是

该列是一个百分比的值估算,rows * filtered/100 可以估算出将要和 explain 中前一个表进行连接的行数(前一个表指 explain 中的id值比当前表id值小的表)。

ps: 在学习时遇到不懂的还是建议先把官方文档看一遍,即便是我这种英语的战五渣,都能硬着头看出个大概,相信各位一定比我强

Extra列

Extra emm额外的,看来是用来展示额外信息的表,那就是不重要咯(狗头)

这里我们只列举出一些常见的值,如果遇到奇怪的自己去官网查呗

Using index

看SQL

EXPLAIN SELECT id,name FROM student;

文档解答 

        The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.

意思也是很清楚,就是我们可以通过一个索引树就拿到结果而不需要额外的开销去查询真实的行数据,

ps: 这里我们不得不提一嘴覆盖索引了(我还是自己查一下吧,毕竟多次出现了)

mysql执行计划explain结果里的key有使用索引,如果select后面查询的字段都可以从这个索引的树中获取,这种情况一般可以说是用到了覆盖索引,extra里一般都有using index;覆盖索引一般针对的是辅助索引,整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值

Using where

使用where查询??  

看SQL

EXPLAIN SELECT * FROM student WHERE id in (1,2,3)

 

文档说明

        A clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the value is not and the table join type is ALL or index. WHEREExtraUsing where

        就是用WHERE 来限制结果, 用在返回值或者表连接, 如果在表链接中且查询类型为ALL 或者 Index 建议加一些条件防止一些问题.

不过看SQL

EXPLAIN SELECT name FROM student WHERE name = 'a';

 这个查询的意思是一个索引解决了? (我们直接可以拿到结果,判断条件是根据索引来的所以无需过滤)

EXPLAIN SELECT NAME FROM student WHERE name > 'a'

 emm既使用了where 还有 index (我们只需要扫描name 二级索引表, 同时在查找到a后我们会向前逐一判断直到重点)(只使用二级索引且过滤了一下)

EXPLAIN SELECT NAME FROM student WHERE id = 1

很显然走了聚簇索引直接拿到值

EXPLAIN SELECT NAME FROM student WHERE id > 1

 注意哈这个其实走的是二级索引, 看key那一列, 并且会对拿出来的数据进行id过滤(我们全表扫描了index(type) 然后过滤出id >1 的列, 并取出name)

Using index condition

这个的名称就已经暴露一切了,使用索引中的条件,肯定和二级索引,和条件查询有关,但是不是 Using Index 代表有些字段找不到呗

EXPLAIN SELECT * FROM  student WHERE name > 'a';

给结论

查询的列不完全被索引覆盖,where条件中是一个前导列的范围

Using temporary

temp我熟啊 临时表呗

EXPLAIN select distinct score from score;

这个的查询就很有意思了 我们下全表扫描score到一个临时表中然后对他进行去重。。

那如果有索引嘞(给score加上索引)

EXPLAIN select distinct score from score;

这让我想起了我以前刷的那些算法,给一个有序列表去重, 简单题

给结论吧

mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化。

 Using filesore

使用 文件排序 ??

文件排序是个啥? 这里买一个伏笔,咱们以后聊,

不过我们看名字, 排序,还文件排序, 听名字就很不妙,首先排序操作, 想什么快排,归并,相信大家因该有所耳闻,我们知道,排序首先要有数据,根据某个字段排序,要么原先这个数据有序,要么就只能全取出来了,同时我们的内存和数据库表的大小之间似乎有一种很微妙的关系,如果我们数据库数据很多,超过了内存空间大小(mySQL 肯定不能把你全部的内存全部拿到,里面肯定有个配置大小的Key)那就更不妙了。这种情况下一般也是要考虑使用索引来优化的。

看SQL

EXPLAIN SELECT * FROM student ORDER BY name;

哎 不对我的name不是建立索引了吗?? 为啥还是全表扫描带排序了??

EXPLAIN SELECT name FROM student ORDER BY name;

看来回表操作也是必须要注意的

Select tables optimized away

选择 表 优秀 离开 emm.... 我匮乏的英语水平

The optimizer determined 1) that at most one row should be returned, and 2) that to produce this row, a deterministic set of rows must be read. When the rows to be read can be read during the optimization phase (for example, by reading index rows), there is no need to read any tables during query execution.

The first condition is fulfilled when the query is implicitly grouped (contains an aggregate function but no GROUP BY clause). The second condition is fulfilled when one row lookup is performed per index used. The number of indexes read determines the number of rows to read.

emm there is no need to read any tables during query execution. 不需要在读表了?

那这个单词的意思应该就是 已经是最优了

这种情况一般是我们使用一些聚合字段时,比如我们type为NULL时那个SQL

EXPLAIN SELECT MAX(id) FROM course;

写在最后 

        最近因为比较懒,经常忘记总结工作,如果某个大佬能看到这里,并且愿意监督我每周一篇博客的话万分感激

        还有的话,孩子比较菜,有些写的东西可能不是很标准,甚至可能出错,如果有大佬指正的话万分感激。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值