MySQL之视图&索引&执行计划(实施必看!!!)

文章目录

  • 前言:
  • 一、视图
    • 1.1含义
    • 1.2操作
    • 1.3实操:
  • 二、索引
    • 2.1什么是索引?
    • 2.2为什么要使用索引?
    • 2.3优点
    • 2.4缺点
    • 2.5何时不使用索引?
    • 2.6索引何时失效
    • 2.7索引分类
  • 三、执行计划
    • 3.1什么是执行计划?
    • 3.2执行计划的作用
    • 3.3执行计划包含的信息
      • 3.3.1ID-获取select子句的操作表顺序,有几种情况
      • 3.3.2SELECT_TYPE查询的类别,主要用于区别普通查询,联合查询,子查询等的复杂查询
      • 3.3.3TABLE-显示这一行的数据是关于哪个表的
      • 3.3.4type-显示的是访问类型
      • 3.3.5possible_keys
      • 3.3.6key
      • 3.3.7key_len
      • 3.3.8ref
      • 3.3.9rows
      • 3.3.10EXtra
  • 四、内连接、外连接、子查询案例
    • 4.1实操-题目:
  • 思维导图:

前言:

上篇博主给大家讲解了MySQL之、CRUD、函数及union查询,本篇给大家带来MySQL之视图&索引&执行计划,
官方解释:**MySQL中的视图是一种虚拟表,它是基于查询结果的可视化表示。视图可以简化复杂的查询操作,并提供了一种安全的方式来访问数据。索引是一种数据结构,用于加快数据库查询的速度。执行计划是MySQL优化器生成的一种描述查询执行方式的计划。**使大家更加的了解MySQL

一、视图

  • 官方解释:视图: 视图可以看作是一个虚拟表,它是基于查询结果的可视化表示。通过创建视图,可以简化复杂的查询操作,并提供了一种安全的方式来访问数据。

1.1含义

  • 虚拟表,和普通表一样使用

1.2操作

  • ①创建视图
create view 视图名
as
查询语句
  • ②视图的修改
方式一:create or replace view 视图名
as
查询语句
方式二:alter view 视图名
as
查询语句
  • ③删除视图
drop view 视图名,视图名...
  • ④查看视图
DESC 视图名;-----查看视图相关字段
SHOW CREATE VIEW 视图名;----查看视图相关语句

1.3实操:

  • 数据库脚本
CREATE TABLE `t_mysql_score`  (
  `sid` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学生编号,外键',
  `cid` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '课程编号,外键',
  `score` float NULL DEFAULT 0 COMMENT '成绩',
  INDEX `sid`(`sid`) USING BTREE,
  INDEX `cid`(`cid`) USING BTREE,
  CONSTRAINT `t_mysql_score_ibfk_1` FOREIGN KEY (`sid`) REFERENCES `t_mysql_student` (`sid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `t_mysql_score_ibfk_2` FOREIGN KEY (`cid`) REFERENCES `t_mysql_course` (`cid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '成绩信息表' ROW_FORMAT = Dynamic;

-- Records of t_mysql_score
-- ----------------------------
INSERT INTO `t_mysql_score` VALUES ('01', '01', 80);
INSERT INTO `t_mysql_score` VALUES ('01', '02', 90);
INSERT INTO `t_mysql_score` VALUES ('01', '03', 99);
INSERT INTO `t_mysql_score` VALUES ('02', '01', 70);
INSERT INTO `t_mysql_score` VALUES ('02', '02', 60);
INSERT INTO `t_mysql_score` VALUES ('02', '03', 80);
INSERT INTO `t_mysql_score` VALUES ('03', '01', 80);
INSERT INTO `t_mysql_score` VALUES ('03', '02', 80);
INSERT INTO `t_mysql_score` VALUES ('03', '03', 80);
INSERT INTO `t_mysql_score` VALUES ('04', '01', 50);
INSERT INTO `t_mysql_score` VALUES ('04', '02', 30);
INSERT INTO `t_mysql_score` VALUES ('04', '03', 20);
INSERT INTO `t_mysql_score` VALUES ('05', '01', 76);
INSERT INTO `t_mysql_score` VALUES ('05', '02', 87);
INSERT INTO `t_mysql_score` VALUES ('06', '01', 31);
INSERT INTO `t_mysql_score` VALUES ('06', '03', 34);
INSERT INTO `t_mysql_score` VALUES ('07', '02', 89);
INSERT INTO `t_mysql_score` VALUES ('07', '03', 98);
-- Table structure for t_mysql_student
-- ----------------------------
DROP TABLE IF EXISTS `t_mysql_student`;
CREATE TABLE `t_mysql_student`  (
  `sid` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学生编号',
  `sname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学生名称',
  `sage` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学生年龄',
  `ssex` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学生性别',
  PRIMARY KEY (`sid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '学生信息表' ROW_FORMAT = Dynamic;
-- Records of t_mysql_student
-- ----------------------------
INSERT INTO `t_mysql_student` VALUES ('01', '赵雷', '1990-01-01', '男');
INSERT INTO `t_mysql_student` VALUES ('02', '钱电', '1990-12-21', '男');
INSERT INTO `t_mysql_student` VALUES ('03', '孙风', '1990-12-20', '男');
INSERT INTO `t_mysql_student` VALUES ('04', '李云', '1990-12-06', '男');
INSERT INTO `t_mysql_student` VALUES ('05', '周梅', '1991-12-01', '女');
INSERT INTO `t_mysql_student` VALUES ('06', '吴兰', '1992-01-01', '女');
INSERT INTO `t_mysql_student` VALUES ('07', '郑竹', '1989-01-01', '女');
INSERT INTO `t_mysql_student` VALUES ('09', '张三', '2017-12-20', '女');
INSERT INTO `t_mysql_student` VALUES ('10', '李四', '2017-12-25', '女');
INSERT INTO `t_mysql_student` VALUES ('11', '李四', '2012-06-06', '女');
INSERT INTO `t_mysql_student` VALUES ('12', '赵六', '2013-06-13', '女');
INSERT INTO `t_mysql_student` VALUES ('13', '孙七', '2014-06-01', '女');
-- Table structure for t_mysql_teacher
-- ----------------------------
DROP TABLE IF EXISTS `t_mysql_teacher`;
CREATE TABLE `t_mysql_teacher`  (
  `tid` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '教师编号',
  `tname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '教师名称',
  PRIMARY KEY (`tid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '教师信息表' ROW_FORMAT = Dynamic;
-- Records of t_mysql_teacher
-- ----------------------------
INSERT INTO `t_mysql_teacher` VALUES ('01', '张三');
INSERT INTO `t_mysql_teacher` VALUES ('02', '李四');
INSERT INTO `t_mysql_teacher` VALUES ('03', '王五');

SET FOREIGN_KEY_CHECKS = 1;
  • 对于实施正常而言,你要给客户排除问题的话,你要去连表查询。
select * from t_mysql_student s,t_mysql_score
sc where s.sid=sc.sid;

MySQL之视图&索引&执行计划(实施必看!!!)_第1张图片

  • 每一次都要这样就很麻烦,所以我们要去创建视图
create view v_student_score
as
select * from t_mysql_student s,t_mysql_score
sc where s.sid=sc.sid;

MySQL之视图&索引&执行计划(实施必看!!!)_第2张图片
那么就需要这样


create view v_student_score
as
select s.*,sc.cid,sc.score from t_mysql_student s,t_mysql_score
sc where s.sid=sc.sid;

MySQL之视图&索引&执行计划(实施必看!!!)_第3张图片
完成之后,就不需要像前面那样去连表查询了
直接查视图就行了,就像操作一张表一样去操作数据

select * from v_student_score;

MySQL之视图&索引&执行计划(实施必看!!!)_第4张图片

  • 查看视图
    ①只能看字段:
desc v_student_score

MySQL之视图&索引&执行计划(实施必看!!!)_第5张图片
②查看我们视图里面的内容,创表语句

show create view v_student_score

MySQL之视图&索引&执行计划(实施必看!!!)_第6张图片

  • 删除视图
drop view v_student_score

MySQL之视图&索引&执行计划(实施必看!!!)_第7张图片
MySQL之视图&索引&执行计划(实施必看!!!)_第8张图片

二、索引

  • 官方解释:索引: 索引是一种数据结构,用于加快数据库查询的速度。它可以帮助数据库系统快速定位到包含特定值的行,从而提高查询性能。

2.1什么是索引?

索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。

2.2为什么要使用索引?

使用索引可以很大程度上提高数据库的查询速度,还有效提高了数据库系统的性能

2.3优点

  • ①通过创建唯一索引可以保证数据库表中每一行数据的唯一性
  • ②可以给所有的MySQL列类型设置索引
  • ③可以大大加快数据的查询速度,这是使用索引最主要的原因
  • ④在实现数据的参与完整性方面可以加速表与表之间的连接
  • ⑤在使用分组和排序子句进行数据查询时也可以显著减少查询中分组和排序的时间

2.4缺点

  • ①创建和维护索引组要耗费时间,并且随着数据量的增加所耗费的时间也会增加。
  • ②索引需要占磁盘空间,除了数据表占数据空间以外,每一个索引主要还要占一定的物理空间。如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸
  • ③当对表中的数据进行增加、删除和修改的时候,索引也要动态维护,这样就降低了数据的维护速度。

2.5何时不使用索引?

  • 表记录太少
  • 经常增删改的表
  • 数据重复且分布均匀的表字段,只应该为经常查询和最经常排序的数据列建立索引(如果某个数据类包含太多的重复数据,建立索引没有太大的意义)
  • 频繁更新的字段不适合创建索引(会增加IO负担)
  • where条件里用不到的字段不创建索引

2.6索引何时失效

  • like以通配符%开头索引失效
  • 当全表扫描比走索引查询的快的时候,会使用全表扫描,而不走索引
  • 当字符串不加单引号索引会失效
  • where中索引列使用了函数(例如substring字符串截取函数)
  • where中索引列有运算(用了右边的索引会失效,用<=or>=索引不会失效)
  • is null 可以走索引,is not null无法使用索引(取决于某一列的具体情况)
  • 复合索引没有用到左列字段(最左前缀法则,如果没有使用到最左列索引,或中间跳过了某列有索引的列,索引会部分失效)
  • 条件中有or,前面的列有索引,后面的列没有,索引会失效。想让索引失效,只能将or条件中的每个列都加上索引

2.7索引分类

CREATE TABLE 't_log'(
'id' varchar(32) NOT NULL COMMENT '唯一标识',
'ip' varchar(15) NOT NULL COMMENT 'IP地址',
'userid' varchar(32) NOT NULL COMMENT '用户ID',
'moduleid' varchar(32) NOT NULL COMMENT '模块ID',
'content' varchar(500) NOT NULL COMMENT '日志内容',
'createdate' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
'url' varchar(100) DEFAULT NULL COMMENT '请求URL地址',
PRIMARY KEY('id')
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • –1)普通索引:最基本的索引,它没有任何限制;
    –0.762 S
    select * from t_log;
    – 建索引前 0.12S
    select * from t_log where moduleid='10040199';
    –创建索引所花费的时间:1.593s
    Create index idx_moduleid on t_log(moduleid);
    –建索引前0.001s
    select * from t_log where moduleid='10040199';
    –可以查看走过的索引
EXPLAIN select * from t_log where moduleid='10040199'
  • –2)唯一索引:与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一;
DUPlicate entry '/quartz/queryJobLst'for key 'idx_url'有重复列段
create UNIQUE index idx_url on t_log(url);
drop index idx_urlon t_log;
  • –3)主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值;
    –主键索引所花费的时间:0s
select * from t_log where id='123456';
EXPLAIN select * from t_log where id='123456';
  • -4)组合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合;
    –花费时间:3.959s
create index idx_userid_moduleid_url on t_log(userid,moduleid,url);

–走组合索引

EXPLAIN select * from t_log where userid="and moduleid = " and url= ";
EXPLAIN select * from t_log where userid = " and moduleid = ";
EXPLAIN select * from t_log where userid = ";
EXPLAIN select * from t_log where userid=" and url =";

–不走组合索引

EXPLAIN select * from t_log where moduleid=";
EXPLAIN select * from t_log where url=";
EXPLAIN select * from t_log where moduleid=" and url=";

–创建索引

CREATE [UNIQUE|FULLTEXT] INDEX 索引名 ON 表名(字段名[(长度)][ASC|DESC])

三、执行计划

  • 官方解释:执行计划: 执行计划是MySQL优化器生成的一种描述查询执行方式的计划。通过执行计划,可以了解MySQL是如何处理查询语句的,包括使用哪些索引、表的连接方式等。

3.1什么是执行计划?

  • 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的sql语句的。分析你的查询语句或是表结构的性能瓶颈。

3.2执行计划的作用

1)表的读取顺序
2)数据读取操作的操作类型
3)哪些索引可以使用
4)哪些索引被实际使用
5)每张表有多少行被优化器查

3.3执行计划包含的信息

3.3.1ID-获取select子句的操作表顺序,有几种情况

1)id相同的情况下执行顺序是由上到下
2)id越大优先级越高,如果是子查询,ID序列号会递增,id值越大,优先级越高,越先执行。
3)id相同又有不相同的,序列号大的会先执行,然后相同的从上到下执行。

3.3.2SELECT_TYPE查询的类别,主要用于区别普通查询,联合查询,子查询等的复杂查询

1)simple:简单的select查询,不包含之查询或者union
2)primary:查询中包含任何复杂的子部分,最外层查询则被标记
3)subquery:在select或者where列表中包含了子查询
4)derived:在from列表中包含子查询被标记为derived Mysql会递归执行这些子查询,把结果放到临时表里
5)union:诺在第二个select中出现union之后,则被标记为union,诺union包含在from子句的子查询中,外层select将被标记为derived
6)union result:从union表获取结果的SELECT

3.3.3TABLE-显示这一行的数据是关于哪个表的

3.3.4type-显示的是访问类型

  • typ是较为重要的一个指标,结果值从最好到最坏的依次是:
system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>all
`注:`一般来说,得保证查询至少达到range级别,最好能达到ref
  • 1)system:表中只有一行记录(等于系统表),这只是const类型的特列,平时不会出现,这个可以忽略不记;
  • 2)const:表示通过索引一次就找到了,const用于比较primary key 或者unqiue索引,因为只匹配一条数据,所以很快,如将主键置于where条件中,MySQL就能将该查询转换一个常量;
  • 3)eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录于之匹配,常见于主键或唯一索引扫描;
  • 4)ref:非唯一索引扫描,返回匹配某个单独值的所有行,常见使用非唯一索查询,组合索引查询;
  • 5)range:只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是在你的where语句中出现了between,<>,in等查询这种范围扫描比全表扫描要好,因为它只需要开始与索引的某一点,而结束与另一点,不用扫描全部索引
  • 6)ALL:全表扫描;
  • 7)index:扫描全部索引树;
  • 8)NULL:MySQL在优化过程中分解语句,执行甚至不用访问表或索引

3.3.5possible_keys

  • 指出MySQL能使用哪个索引在该表中找到行。查询涉及到的字段上诺存在索引,则该索引将被列出,但不一定被查询使用。如果是空的,没有相关的索引。这时要提高性能,可通过检验WHERE子句,看是否引用某些字段,或者检查字段不是适合索引。简而言之:可能使用的key(索引)

3.3.6key

  • 实际上使用的索引,如果没用索引,则为NULL,查询中诺使用了覆盖索引,则该索引和查询的select字段重叠。

3.3.7key_len

  • 显示MySQL决定使用的键长度。表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。如果键是NULL,长度就是NULL,特别注意这个值可以得出一个多重主键里MySQL实际使用了哪一部分。

3.3.8ref

  • 显示哪个字段或常数与key一起被使用

3.3.9rows

  • 这个数表示MySQL要遍历多少数据才能找到,表示MySQL根据表统计信息及索引选用情况,估算的找到所需要的记录所需要读取的行数,在innodb上可能是不准确的。
  • 包含不合适在其他列中显示但十分重要的额外信息:

3.3.10EXtra

  • 包含不合适在其他列中显示但十分重要的额外信息:
    1)Using index 此值表示mysql将使用覆盖索引,以避免访问表。
    2)Using Where mysql将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
    3)Using temporary mysql 对查询结果排序时会使用临时表
    4)Using filesort mysql会对结果使用一个外部索引排序而不是按索引次序
    从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序在内存里还是磁盘上完成。

四、内连接、外连接、子查询案例

4.1实操-题目:

  • 数据脚本上面给了
    MySQL之视图&索引&执行计划(实施必看!!!)_第9张图片
    MySQL之视图&索引&执行计划(实施必看!!!)_第10张图片
    MySQL之视图&索引&执行计划(实施必看!!!)_第11张图片
    MySQL之视图&索引&执行计划(实施必看!!!)_第12张图片
    01)查询" 01 “课程比” 02 "课程成绩高的学生的信息及课程分数
    ①分析:涉及表 t_mysql_student,t_mysql_score 这个学生既要有01的分数也要有02的分数,那么这张表要当两次来用
    ②连接方式:内连接
    ③行转列:流程函数
SELECT
	s.*,
	( CASE WHEN t1.cid = '01' THEN t1.score END ) 语文,
	( CASE WHEN t2.cid = '02' THEN t2.score END ) 数学 
FROM
	t_mysql_student s,
	( SELECT * FROM t_mysql_score WHERE cid = '01' ) t1,
	( SELECT * FROM t_mysql_score WHERE cid = '02' ) t2 
WHERE
	s.sid = t1.sid 
	AND t1.sid = t2.sid 
	AND t1.score > t2.score;

MySQL之视图&索引&执行计划(实施必看!!!)_第13张图片
02)查询同时存在" 01 “课程和” 02 "课程的情况
①分析:涉及表 t_mysql_student,t_mysql_score 这个学生既要有01的分数也要有02的分数,那么这张表要当两次来用
②连接方式:内连接
③行转列:流程函数

SELECT
	s.*,
	( CASE WHEN t1.cid = '01' THEN t1.score END ) 语文,
	( CASE WHEN t2.cid = '02' THEN t2.score END ) 数学 
FROM
	t_mysql_student s,
	( SELECT * FROM t_mysql_score WHERE cid = '01' ) t1,
	( SELECT * FROM t_mysql_score WHERE cid = '02' ) t2 
WHERE
	s.sid = t1.sid 
	AND t1.sid = t2.sid;

MySQL之视图&索引&执行计划(实施必看!!!)_第14张图片
03)查询存在" 01 “课程但可能不存在” 02 "课程的情况(不存在时显示为 null )
①连接方式:外连接
②行转列:流程函数

SELECT
s.*,
( CASE WHEN t1.cid = '01' THEN t1.score END ) 语文,
( CASE WHEN t2.cid = '02' THEN t2.score END ) 数学 
FROM
	t_mysql_student s
	INNER JOIN ( SELECT * FROM t_mysql_score WHERE cid = '01' ) t1 ON s.sid = t1.sid
	LEFT JOIN ( SELECT * FROM t_mysql_score WHERE cid = '02' ) t2 ON t1.sid = t2.sid;

MySQL之视图&索引&执行计划(实施必看!!!)_第15张图片
04)查询不存在" 01 “课程但存在” 02 "课程的情况
①分析:先查出存在01的学生有哪些,然后再排除掉。子查询

SELECT
	s.*,
	( CASE WHEN sc.cid = '01' THEN sc.score END ) 语文,
	( CASE WHEN sc.cid = '02' THEN sc.score END ) 数学 
FROM
	t_mysql_student s,
	t_mysql_score sc 
WHERE
	s.sid = sc.sid 
	AND s.sid NOT IN ( SELECT sid FROM t_mysql_score WHERE cid = '01' ) 
	AND sc.cid = '02'

MySQL之视图&索引&执行计划(实施必看!!!)_第16张图片
05)查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
①分析:聚合函数意味着分组,外连接

SELECT
	s.sid,
	s.sname,
	round( avg( sc.score ), 2 ) 平均成绩 
FROM
	t_mysql_student s
	LEFT JOIN t_mysql_score sc ON s.sid = sc.sid 
GROUP BY
	s.sid,
	s.sname 
HAVING
	平均成绩 >= 60

MySQL之视图&索引&执行计划(实施必看!!!)_第17张图片
06)查询在t_mysql_score表存在成绩的学生信息
①分析:表两张:学生表,成绩表。内连接

SELECT
	s.sid ID,
	s.sname 姓名 
FROM
	t_mysql_student s
	INNER JOIN t_mysql_score sc ON s.sid = sc.sid 
GROUP BY
	s.sid,
	s.sname

MySQL之视图&索引&执行计划(实施必看!!!)_第18张图片
07)查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
①分析:聚合函数
②外连接

SELECT
	s.sid,
	s.sname,
	count( sc.score ) 选课总数,
	sum( sc.score ) 总成绩 
FROM
	t_mysql_student s
	LEFT JOIN t_mysql_score sc ON s.sid = sc.sid 
GROUP BY
	s.sid,
	s.sname

MySQL之视图&索引&执行计划(实施必看!!!)_第19张图片
08)查询「李」姓老师的数量

select count(*) 数量 from t_mysql_teacher where tname like '李%'

MySQL之视图&索引&执行计划(实施必看!!!)_第20张图片

思维导图:

你可能感兴趣的:(实施运维工程师,mysql,数据库)