🌈MySQL真的就CRUD吗?✨来看看2k和12k之间的差距(上)

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战mysql

🌈往期回顾

    感谢阅读,但愿能对你有所帮助,博文如有瑕疵请在评论区留言或在主页我的介绍中添加我私聊我,感谢每一位小伙伴不吝赐教。我是XiaoLin,既会写bug也会唱rap的男人算法

1、MySql 的用户和权限管理

1.一、MySQL的用户管理

1.1.一、相关命令

命令 描述 备注
create user xiaolin identified by '123456'; 建立名称为xiaolin的用户,密码为123456
select host,user,password,select_priv,insert_priv,drop_priv from mysql.user; 查看用户和权限的相关信息
set password = password('123456') 修改其余用户的密码 全部经过 user 表的修改,必须用 flush privileges;命令才能生效
update mysql.user set user = 'zs' where user = 'xiaolin' 修改用户名 全部经过 user 表的修改,必须用 flush privileges;命令才能生效
drop user xiaolin 删除用户 不要经过delete from user where user = 'xiaolin'进行删除,系统会有残留信息保存

1.1.二、详解

image-20210524101653451

host

    host表示链接类型。sql

  1. %:表示全部远程经过TCP方式链接。
  2. 127.0.0.1:经过指定IP进行的TCP方式的链接。
  3. 机器名:经过指定网络中的机器名进行的TCP方式的链接。
  4. ::1:IPV6的本地IP地址,等同于IPV4的127.0.0.1
  5. localhost 本地方式经过命令行方式的链接 ,好比 mysql -u xxx -p 123xxx 方式的链接。

user

    user表示用户名,同一用户经过不一样方式链接的权限是不同的。数据库

password

    这里显示的是明文密码经过哦MYSQLSHA1加密算法加密后获得的密文密码,是不可逆的,mysql 5.7 的密码保存到 authentication_string 字段中再也不使用 password 字段。缓存

select_priv , insert_priv等

    表示该用户所拥有的权限。安全

1.二、MySQL的权限管理

1.2.一、授予权限

    咱们能够经过命令来授予用户权限,该权限若是发现没有该用户,则会直接新建一个用户。服务器

    格式为:markdown

grant 权限 1,权限 2,…权限 n on 数据库名称.表名称 to 用户名@用户地址 identified by‘链接口令
复制代码

    示范:网络

# 给 xiaolin 用户用本地命令行方式下,授予 user 这个库下的全部表的插删改查的权限。
grant select,insert,delete,drop on user.* to xiaolin@localhost;

# 授予经过网络方式登陆的的 xiaolin 用户 ,对全部库全部表的所有权限,密码设为 123.
grant all privileges on *.* to xiaolin@'%' identified by '123';
复制代码

1.2.二、查看权限

    咱们可使用命令来查看当前用户的权限。数据结构

show grants;
复制代码

1.2.三、收回权限

    咱们可使用命令来收回用户的权限,权限收回后,必须用户从新登陆后,才能生效。

revoke
[权限 1,权限 2,…权限 n] on 库名.表名 from 用户名@用户地址 ;
复制代码

示范:

# 收回全库全表的全部权限
REVOKE ALL PRIVILEGES ON mysql.* FROM joe@localhost;

# 收回 mysql 库下的全部表的插删改查权限
REVOKE select,insert,update,delete ON mysql.* FROM xiaolin@localhost;
复制代码

2、MySQL逻辑架构

2.一、总体架构图

image-20210524141914538

    和其它数据库相比,MySQL 有点不同凡响,它的架构能够在多种不一样场景中应用并发挥良好做用。主要体如今存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构能够根据业务的需求和实际须要选择合适的存储引擎。

2.二、MySQL分层

MySql大概分为四层:

MySQL分层

2.2.一、链接层

    最上层是一些客户端和链接服务,包含本地 sock 通讯和大多数基于客户端/服务端工具实现的相似于 tcp/ip 的通讯。主要完成一些相似于链接处理、受权认证、及相关的安全方案。在该层上引入了线程池的概念,为经过认证安全接入的客户端提供线程。一样在该层上能够实现基于 SSL 的安全连接。服务器也会为安全接入的每一个客户端验证它所具备的操做权限。

2.2.二、服务层

    服务层提供各类用户使用的接口,同时提供SQL优化器,对用户传进来的SQL语句进行优化。他有几个组件。

组件名 描述
Management Serveices & Utilities 系统管理和控制工具
SQL Interface SQL 接口。接受用户的 SQL 命令,而且返回用户须要查询的结果。好比 select from就是调用 SQL Interface
Parser 解析器。 SQL 命令传递到解析器的时候会被解析器验证和解析
Optimizer 查询优化器。SQL 语句在查询以前会使用查询优化器对查询进行优化,好比有where 条件时,优化器来决定先投影仍是先过滤。
Cache 和 Buffer 查询缓存。若是查询缓存有命中的查询结果,查询语句就能够直接去查询缓存中取数据。这个缓存机制是由一系列小缓存组成的。好比表缓存,记录缓存,key 缓存,权限缓存等

2.2.三、引擎层

    存储引擎层,存储引擎真正的负责了 MySQL 中数据的存储和提取,服务器经过 API 与存储引擎进行通讯。不一样的存储引擎具备的功能不一样,这样咱们能够根据本身的实际须要进行选取。

2.2.四、存储层

    数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

2.三、MySQL的查询流程

    mysql 的查询流程大体是:

  1. MySQL客户端经过协议与MySQL服务器创建链接,发送查询语句。
  2. 服务器收到了查询语句以后,会先去检查查询缓存,这个缓存存储了SELECT语句以及相应的查询结果集。若是命中(查询结果已经位于缓存中)服务器就不会再对查询进行解析、优化、执行,他作的仅仅是将缓存中的结果直接返回给用户,大大提高了性能。若是没有命中缓存的话,将会进行第三步。
  3. 接下来进入的是语法解析器和预处理,首先MySQL经过关键字将SQL进行解析,并生成一颗对应的解析树。MySQL解析器将使用MySQL语法规则验证解析查询,预处理器则根据一些MySQL规则进一步检查解析是否合法。
  4. 接着到了查询优化器,解析树由优化器转化为执行计划。一条查询能够有不少种执行方式,可是最后都返回相同的结果,优化器的做用就是找到其中最好的执行计划。
  5. 最后交有存储引擎进行执行返回给客户端。

MySQL执行流程

2.四、MySQL的执行顺序

    咱们手写一条完整的SQL大概是这样写的。

SELECT DISTINCT
    < select_list >
FROM
    < left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
    < where_condition >
GROUP BY
    < group_by_list >
HAVING
    < having_condition >
ORDER BY
    < order_by_condition >
LIMIT < limit_number >
复制代码

    然而它的执行顺序是这样的.。

FROM <left_table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT
DISTINCT <select_list>
ORDER BY <order_by_condition>
LIMIT <limit_number>
复制代码

image-20210524171827989

2.五、MyISAM 和 InnoDB

对比项 MyISAM InnoDB
外键 不支持 支持
事务 不支持 支持
行表锁 表锁,即便操做一条记录也会锁住整张表,不适合高并发操做 行锁,操做时只锁住某一行,不对其余行有影响,适合高并发操做
缓存 只缓存索引不缓存真实数据 不只仅缓存索引还缓存真实数据,对内存要求较高,并且内存大小对性能有决定性的影响

3、索引

3.一、索引的概述

3.1.一、索引是什么

    MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。能够获得索引的本质:索引是数据结构。能够简单理解为排好序的快速查找数据结构。

    在数据以外,数据库系统还维护着知足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就能够在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

image-20210524211732444

    左边是数据表,一共是两列七条数据,最左边的是数据记录的物理地址。为了加快 Col2 的查找,能够维护一个右边所示的二叉查找树,每一个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就能够运用二叉查找在必定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。

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

3.二、索引的优缺点

3.2.一、优势

  1. 提升数据检索的效率,下降数据库的IO成本。
  2. 经过索引列对数据进行排序,下降数据排序的成本,下降了CPU的消耗。

3.2.二、缺点

  1. 虽然索引大大提升了查询速度,同时却会下降更新表的速度,如对表进行INSERT、UPDATE和DELETE。由于更新表时,MySQL不只要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整由于更新所带来的键值变化后的索引信息。
  2. 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,因此索引列也是要占用空间的。

3.二、Btree 索引

3.2.一、初始化介绍

    MySQL 使用的是 Btree 索引。一颗B树,浅蓝色的块咱们称之为一个磁盘块,能够看到每一个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示)。

image-20210524212305101

    磁盘块 1 包含数据项 17 和 35,包含指针 P一、P二、P3,P1 表示小于 17 的磁盘块,P2 表示在 17 和 35 之间的磁盘块,P3 表示大于 35 的磁盘块。

    真实的数据存在于叶子节点即 三、五、九、十、1三、1五、2八、2九、3六、60、7五、7九、90、99。

    非叶子节点只不存储真实的数据,只是为了做为分隔线,存储指引搜索方向的数据项,如 1七、35 并不真实存在于数据表中。

3.2.二、查找过程

    若是要查找数据项 29,那么首先会把磁盘块 1 由磁盘加载到内存,此时发生一次 IO。

    在内存中用二分查找肯定 29在 17 和 35 之间,锁定磁盘块 1 的 P2 指针,内存时间由于很是短(相比磁盘的 IO)能够忽略不计。经过磁盘块 1的 P2 指针的磁盘地址把磁盘块 3 由磁盘加载到内存,发生第二次 IO。

    29 在 26 和 30 之间,锁定磁盘块 3 的 P2 指针,经过指针加载磁盘块 8 到内存,发生第三次 IO,同时内存中作二分查找找到 29,结束查询,总计三次 IO。

    3层的B树能够表示上百万的数据,若是上百万的数据查找只须要三次 IO,性能提升将是巨大的。

    若是没有索引,每一个数据项都要发生一次 IO,那么总共须要百万次的 IO,显然成本很是很是高。

3.三、B+tree 索引

    咱们能够看到BTree结构图中,每一个节点不只仅包含key值,同时还有data值,每个页的存储空间是有限的,若是data数据较大时会致使每一个节点(即每个页)能存储的key数量很小,当存储的数据量很大的时候会致使BTree的深度很深,增大了查询时磁盘I/O的次数。

    而在B+Tree中,全部数据记录节点都是按照键值大小顺序放在同一层的叶子节点上,而非叶子节点只存储key信息,这样能够大大增长每一个节点存储的key值的数量,下降B+Tree的高度。

    实际状况中每一个节点可能不能填满,在数据库中,B+Tree的高度通常在24层之间,MySQL的InnoDB存储引擎在设计时是将根节点常驻内存的(不动用磁盘I/O,直接上内存找),也就是说查找某一键值行记录时最多只须要13次磁盘I/O操做。

image-20210524212903582

3.四、B+Tree 与 B-Tree 的区别

  1. B-树的关键字和记录是放在一块儿的,叶子节点能够看做外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
  2. 在 B-树中,越靠近根节点的记录查找时间越快,只要找到关键字便可肯定记录的存在;而 B+树中每一个记录的查找时间基本是同样的,都须要从根节点走到叶子节点,并且在叶子节点中还要再比较关键字。从这个角度看好像B-树的性能1是要比B+树的性能要高,而在实际应用中确实B+树的性能更好一些。由于B+树的非叶子节点不存放实际的数据,这样每一个11节点1可容纳的元素个数比B-树多,可是依次磁盘访问的时间至关于成千上百次内存比较的时间,所以在实际中B+树性能更好,并且B+树的叶子节点1是使用指针链接在一块儿,方便顺序遍历。

3.五、为何B+树比 B树更适合实际应用

  1. B+树的磁盘读写代价更低:B+树的内部结点并无指向关键字具体信息的指针。所以其内部结点相对 B 树更小。若是把全部同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的须要查找的关键字也就越多。相对来讲 IO 读写次数也就下降了。
  2. B+树的查询效率更加稳定:因为非终结点并非最终指向文件内容的结点,而只是叶子结点中关键字的索引。因此任何关键字的查找必须走一条从根结点到叶子结点的路。全部关键字查询的路径长度相同,致使每个数据的查询效率至关。

3.六、聚簇索引和非聚簇索引

  1. 聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据,聚簇索引默认是主键。
  2. 非聚簇索引:也称为辅助索引,将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置。非聚簇索引存储的再也不是行的物理位置,而是主键值,辅助索引访问数据老是须要二次查找。不存储物理位置的缘由是当数据发生增删改的时候,物理位置可能会发生改变,万一发生了改变,那么还须要维护非聚簇索引。

image-20210525222603449

  • 聚簇索引查找:将主键组织到一个B+Tree树中,而行数据就存储在叶子节点上,若使用'where id = 14'这样的条件查找主键时,则按照B+Tree的检索算法便可查找到对应的叶子节点,从而得到行数据。
  • 若对name(辅助索引)列进行条件搜索则须要两个步骤:
    1. 第一步先在辅助索引B+Tree中检索name,到达其叶子节点对应的主键。
    2. 使用主键在主索引B+Tree中再执行一次B+Tree检索操做,最终到达叶子节点便可获取整行数据。

3.6.一、聚簇索引的好处

  1. 因为行数据和聚簇索引的叶子节点存储在一块儿,同一页中会有多条行数据,访问统一数据页不一样记录时,已经把页加载到了buffer(缓存器),再次访问时,会在内存中完成访问,没必要访问磁盘。这样主键和行数据时一块儿载入内存的,找到叶子节点就能够马上将数据返回了,若是按照主键ID来组织数据的话,得到数据更快。
  2. 辅助索引的叶子节点是存储主键的,而不是数据的存放地址。好处是当行数据发生改变时,索引树节点也是须要分裂变化的,另外一个好处是由于辅助索引存放的是主键值,减小了辅助索引占用的存储空间大小。

3.6.二、聚簇索引的限制

  1. 对于 mysql 数据库目前只有 innodb 数据引擎支持聚簇索引,而 Myisam 并不支持聚簇索引。
  2. 因为数据物理存储排序方式只能有一种,因此每一个 Mysql 的表只能有一个聚簇索引。通常状况下就是该表的主键。
  3. 为了充分利用聚簇索引的聚簇的特性,**因此 innodb 表的主键列尽可能选用有序的顺序 id,而不建议用无序的 id,好比 uuid 这种。**若是id比较大的1话,能够选择雪花算法1得出的id。
  4. 建议使用int自增的类型,方便排序且默认会在索引树末尾增长主键值,对索引树结构影响最小。聚簇索引的数据的物理存放顺序是一致的,由于索引是相邻的,那么对应的数据必定也是相邻地存放在磁盘上的,若是主键不是自增id,那么它会不断地调整物理地址、分页,但若是是自增,那么他只需一页页地写索引结构相对紧凑,磁盘碎片较少,效率高。

3.七、索引的分类

3.7.一、单值索引

3.7.1.一、概述

    单值索引指一个索引只包含单个列,一个表能够有多个单列索引。

3.7.1.二、语法

# 随着表的创建一块儿创建
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id), KEY (customer_name) );

# 单独建单值索引
CREATE INDEX idx_customer_name ON customer(customer_name);
复制代码

3.7.二、惟一索引

3.7.2.一、概述

    惟一索引指的是索引列必须惟一,可是容许有空值,且只能有一个。

3.7.2.二、语法

# 随着表的创建一块儿创建
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id), KEY (customer_name), UNIQUE (customer_no) );

# 单独建惟一索引
CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);
复制代码

3.7.三、主键索引

3.7.3.一、概述

    设定为主键后数据库会自动创建索引,innodb为聚簇索引,主键索引列值不能为空。

3.7.3.二、语法

# 随表一块儿建索引
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id) );

# 单独建主键索引
ALTER TABLE customer add PRIMARY KEY customer(customer_no);

# 删除建主键索引
ALTER TABLE customer drop PRIMARY KEY ;

# 若是须要修改建主键索引,必须先删除掉(drop)原索引,再新建(add)索引
复制代码

3.7.四、复合索引

    他会符合两个原则:

  1. 最左匹配原则。
  2. MySQL引擎在查询时为了更好的利用索引,在查询过程当中会动态调整查询字段的顺序,以便于更好地利用索引。

3.7.4.一、概述

    复合索引是一个索引包含多个列。

3.7.4.二、语法

# 随表一块儿建索引
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id), KEY (customer_name), UNIQUE (customer_name), KEY (customer_no,customer_name) );

# 单独建索引
CREATE INDEX idx_no_name ON customer(customer_no,customer_name);
复制代码

3.八、索引的建立时机

3.8.一、适合建立索引的时机

  • 主键自动创建惟一索引。
  • 频繁做为查询条件的字段应该建立索引。
  • 查询中与其余表关联的字段,外键关系创建索引。
  • 单键/组合索引面临选择的适合,通常选择组合索引性价比更高。
  • 查询中排序的字段,排序字段若经过1索引去访问将大大提升排序的1速度。
  • 查询中统计或者分组字段。

3.8.二、不适合建立索引的状况

  • 表记录太少。
  • 常常增删改的表或者字段。
  • where条件里用不到的字段不建立索引。

3.九、索引的基本操做

3.9.一、主键索引

    主键索引是在建表时自动建立的。

建表,主键自动建立主键索引

create table t_user(id varchar(20) primary key,name varchar(20));
复制代码

查看索引

show index from t_user;
复制代码

image-20210604150311834

3.9.二、单列索引

创表的时候一块儿建立索引

# 在建表的时候字段后面用key(列名)来建立索引,可是咱们没办法指定索引名,默认索引名和列名一致。
create table t_user(id varchar(20) primary key , name varchar(20 , key(name)))
复制代码

建立完表之后加索引

# 语法格式
create index 索引名 on 表名(列名);

# 示范
create index index_name on t_user(name);
复制代码

image-20210604150718129

删除索引

# 语法格式
drop index 索引名 on 表名;

# 示范
drop index index_name on t_user;
复制代码

3.9.三、惟一索引

建表的时候建立索引

# 在建表的时候字段后面用unique(列名)来建立索引,可是咱们没办法指定索引名,默认索引名和列名一致。
create table t_user(id varchar(20) primary key , name varchar(20) , unique(name) );
复制代码

建立表以后建立索引

# 格式
create unique index 索引名 on 表名(列名);

# 示范
create unique index index_name on t_user(name);
复制代码

3.9.四、复合索引

建表的时候建立索引

# 在建表的时候字段后面用key(列名1,列名2...)来建立索引,可是咱们没办法指定索引名,默认索引名和列名一致。
create table t_user (id varchar(20) primary key , name varchar(20) , age int , key(name , age) );
复制代码

建表以后建立

# 语法格式
create index 索引名 on 表名(列名1,列名2...);

# 示范
create index index_name_age on t_user (name , age);
复制代码
相关文章
相关标签/搜索