MySQL数据库|视图+索引

视图

视图是一个虚拟的表,它是基于一个或多个基础表或其他视图的的查询的结果集视图本身是不存储数据的

语法:create view view_name [(colum list)] as select_statement

view创建视图的关键字

view_name视图名

colum list视图中包含的列

select_statement视图对应的SQL语句

查询用户的所有信息和考试成绩

学生ID,学生成绩,所在班级,课程和对应成绩

所有有这样的开发需求的程序员,都需要写这么复杂的SQL

可以把以上SQL定义成一个视图

创建视图

创建视图时要注意名字不能重复

查看视图

使用视图

创建视图时指定列

指定列名后,视图会根据指定的列名创建,查询结果集中是否重名不重要

基本表数据修改是否会影响到视图?

更新基本表基本数据

此时检查视图是否受到影响

更新表之后,视图会查到最新数据

那么更新视图是否会影响基本表

更新视图

通过更新将视图中的score改成80

创建视图时使用order by时,视图不允许修改

但修改不使用order by创建的视图时,修改时成功的

那么有哪些视图是可以修改的

1.创建视图时使用聚合函数的视图

2.创建视图时使用 DISTINCT

3.创建视图时使用 GROUP BY 以及 HAVING 子句

4.创建视图时使用 UNION 或 UNION ALL

5.查询列表中使用子查询

6.在FROM子句中引用不可更新视图

7.使用order by

查询视图和基础表

更新视图时是会影响基础表

不论更新视图还是基础表,相互都会被影响,查询出来的数据都是最新的结果

删除视图

语法:drop view view_name;

视图的优点

简单性:视图可以将复杂的查询封装成一个简单的查询

安全性:通过视图,可以隐藏表中的敏感数据

逻辑数据独立性:视图提供了一种逻辑数据独立性,即使底层表结构发生变化,只需修改视图定 义,而无需修改依赖视图的应用程序。

重命名列:视图允许用户重命名列名,以增强数据可读性。

索引

MySQL 索引是一种数据结构,高效的查询结构。类似于书籍的目录,通过指向数据行的位置,可以快速定位和访问表中的数据

索引的数据结构

HASH

时间复杂度:O(1) 最重要的数据结构,没有之一

不支持范围查找,只支持一对一查询

二叉搜索树

中序遍历是一个有序序列-->支持范围查找

时间复杂度:可能退化成一个单边树O(N)

节点个数过多时,无法保证树的高度

由于数据库中的数据是磁盘上保存的,每一次访问子节点都会发生一次磁盘IO

磁盘IO是制约数据库性能的主要因素

N叉树

每个节点可以有超过两个的子节点,可以解决树高的问题

时间复杂度:O(logN)

在数据量相同的情况下,可以有效的控制树高,也就是说可以使用更少的IO的次数找到目标节点,从而提高数据库的效率

B+树

时间复杂度:O(logN)

可以有效的控制树高

B+树与B树对比

1.叶子节点之间有一个相互连接的引用,可以通过一个叶子节点找到它相信的兄弟节点

MYSQL在组织也直接点时使用的是双向链表

2.非叶子节点的值都包含在叶子节点

MYSQL非叶子节点只保存了对叶子节点的引用,没有保存真实的数据,所有真实的数据都保存在叶子节点中

3.对于B+树而言,在相同树高的情况下,查找任意元素的时间复杂度都一样,性能均衡(因为都会遍历到叶子节点)

索引在整个数据检索的过程中如何工作,要从MySQL存储结构说起

MySQL中的页

为什么要使用页

页是内存与磁盘交互的最小单位,默认大小是16KB,每次内存与磁盘交互至少读取一页,所以磁盘中每个页内部的地址都是连续的,同时,根据局部性原理,将要使用的数据与当前访问的数据在空间上是临近的,所以一次从磁盘中读取一页的数据放入内存中,从而减少磁盘I/O提高性能

每一个页即使没有数据也会使用16KB的存储空间,同时与索引的B+树中的节点对应

innodb存储引擎后形成的表空间文件后缀是.ibd

但Linux操作系统中管理文件的最小单位是4KB

MYSQL作为一个数据库程序,以4KB大小管理数据显然是太少了,所以定义了16KB一页的默认大小

但此时内存向磁盘写数据页时是会将原来16KB的文件拆分成4个4KB文件依次写入

如果此时数据写入一半操作系统挂了,这时MYSQL应该如何去保证数据安全?

其实,在数据落盘之前会记录各种日志,保证重启之后可以找到没有落盘的数据内容

现在具体查看页的大小

16384/1024=16KB

具体原理

以任意一个以.ibd结尾的文件为例

每创建一张表生成一个保存数据的文件称为独立表空间文件

一个独立表空间文件含有页文件头,页主体,页文件尾

页文件头和页文件尾

页头含有当前页的主要信息,同时含有上一页页号和下一页页号,所以可以通过页头来锁定上一页和下一页

上一页页号和下一页页号,通过这两个属性可以把页与页之间连接起来,形成一个双向链表

通过页号和页大小,可以计算出下一页和上一页在磁盘上的偏移量

页主体

保存真实数据的主要区域,每当创建一个新页,都会自动分配两个行,一个页内最大行与一个页内最小行,这两个行不存储任何真实数据,而是作为数行链表的头和尾

插入的行数会按主键从小到大的顺序进行连接

同时,指向的会是想的数据行的数据行的行信息区与数据区之间,因为这样更方便查找所需要的信息

页目录

像数据表中查询数据时不会直接去从头到尾一个一个去查找,而是通过页目录中的槽来锁定想要查找的数据大概位置,然后从数据所在组的上一组数据的尾部开始查找

具体解释下何为槽,创建分组时会在页目录中创建一个槽,槽的数量与分组的数据是一致的,槽会指定对应分组的最后条记录,同时保存这条记录主键值

最小行单独为一组

数据行的分组,每一个分组最多可以容纳8条记录,超过8条记录会分裂出来一个新的组,最大行永远在最后一个分组中

例如要查找主键为特定某值行

1.首先要找到这条记录所有的页

2.在页中找到所在的槽

3.在分组中找到对应的记录

数据页头

数据页头记录了当前页保存数据相关的信息

B+树在MYSQL索引的引用

非叶子节点保存索引数据,叶子节点保存数据的真实数据,如下图所示

以查找id为5的记录,完整的检查过程如下图所示:

1.首先判断B+树的根节点的索引记录,此时5<7,应访问左孩子节点,找到索引页2

2.在索引页2中判断id的大小,找到与5相关的记录,命中,加载对应的数据页

以上的IO过程,加载索引页1->加载索引页2->加载索引页3 (3次IO)

内存会将索引页加载到内存中进行缓存,当查到一条没有加载过的数据时,一次真实IO就可以搞定

索引分类

主键索引

当在一个表上定义主键PRIMARY KEY时,会自动创建索引键,索引键的值时主键列的值,innoDB使用它作为聚焦索引(也叫聚簇索引)

普通索引

最基本的索引类型,没有唯一限制

可能为多列创建组合索引,称为复合索引或组合索引

创建的索引会生成一颗索引树,创建多少索引生成多少索引树

生成的索引树也会占用磁盘空间,创建索引时,要慎重考虑需不需要,索引树越多,对增删改的效率影响越大

注意:为了提升查询效率,工作中通常为查询频繁的列创建索引(列的值重复度不高)

唯一索引

当在一个表上定义一个唯一键UNQUE时,自动创建唯一索引

与普通索引相似,但唯一区别在于唯一索引的列不允许有重复键

全文索引

基于文本列创建的索引,用于全文索引,仅MyLSAM和innoDB引擎支持

聚集索引

与主键索引是同义词

如果没有为表定义PRIMARY KEY,innoDB使用第一个UNIQUE和NOT NULL的列作为聚集索引

如果没有合适的索引,innoDB会为新插入的行生成一个行号并用6字节的ROW_ID字段记录(ROW_ID是数据行中的一个隐藏列之一),使用ROW_ID作为索引

聚集索引可以标识数据行的唯一性

非聚集索引

聚集索引以外的索引称为非聚集索引活二级索引

二级索引中的每条记录都包含该行的主列键,以及二级索引指定的列

innoDB使用这个主键来收索聚集索引中的行,这个过程称为回表查询

索引覆盖

不用进行回表查询,可以在当前列表中查询到需要的值

提问:当前的组合索引中通过学号来查找姓名的索引生不生效

select name from student where name sn = '100002'

创建索引时,name在sn列之前,那么使用的时候也要先使用name在使用sn,如果只是用sn列,那么索引就会失效,如果非要使用sn查询,可以使用sn单独创建一个索引

使用索引

自动创建

当我们为一张表加主键约束,外键约束,唯一约束时,MySQL会为对应的的列自动创建一个索引

手动创建

主键索引

三种创建方式

创建表的时候指定主键

创建表的时候单独指定主列键

修改表中的id列为主键索引

修改表的结构和列

alter table 表名 [add|modify|drop] 要修改的内容

唯一索引

更主键索引一样有三种创建方式

普通索引

创建的时机:

1.创建表的时候,明确的知道某些列频繁查询,就创建好(当表中数据过少的时候,全表扫描可能效率还比索引高)

2.随着业务的不断发展,在版本迭代的过程中添加索引

创建仍有三种方式

创建表的时候创建普通索引

index是创建索引的关键字index(索引列)

修改表中的列为普通索引

单独创建索引并指定索引名

关于create index创建

语法:create index index_name on t_test_index2(sno);

创建复合索引

创建语法与创建普通索引相同,只不过指定多个列,列与列之间用逗号隔开

创建表时指定索引列

修改表中的列为复合索引

单独创建索引并指定索引名

查看索引

方式一:show keys from 表名

方式二 show index from 表名

方式三:简要信息:desc 表名;

删除索引

主键索引

语法:alter table 表名 drop PRIMARY KEY;

如果主键是自增列时,先把自增列改成非自增列

再执行主键

其他索引

删除其它索引

alter table 表名 drop index index_name;

其它

怎么去查看自己写的SQL走没走索引?

可以查看执行计划,explain

先为学生表创建一个索引

1.不加条件,查询所有

这个结果就explain后面的SQL语句的执行计划

2.使用主键查询

3.子查询中使用索引

关于type的访问类型

4.使用普通索引

5.使用复合索引

存在两种情况,一种需要回表查询,一种需要索引覆盖

但也存在特殊情况,例如索引对象顺序弄反会出现其他情况

对于using where,有以下解释

但还有一种特殊情况

相关推荐
SQVIoMPLe2 小时前
[拆解LangChain执行引擎]以Actor模型的视角来看Pregel
服务器·数据库·langchain
你都会上树?2 小时前
Ubuntu22 安装PostgreSQL
数据库·postgresql
想唱rap2 小时前
线程之条件变量和生产消费模型
java·服务器·开发语言·数据库·mysql·ubuntu
RInk7oBjo3 小时前
MySQL的编译安装
数据库·mysql·adb
java资料站3 小时前
MySQL 增量同步脚本
android·数据库·mysql
ningmengjing_3 小时前
从零推导出 Redis
数据库·redis
殷紫川3 小时前
InnoDB 索引性能天花板:聚簇 & 二级索引存储本质拆解,覆盖索引零回表优化全攻略
mysql
IvorySQL3 小时前
PostgreSQL & IvorySQL 技术交流 Meetup・郑州站| 4.18 线下开讲,只聊硬核技术
数据库·postgresql·开源
殷紫川3 小时前
MySQL IN 里塞 10000 个值?90% 开发者都踩过的坑,底层原理 + 全场景解决方案一次讲透
mysql