MySQL学习笔记(三)



1.存储引擎

1.1介绍

1.1.1mysql体系结构

在这里插入图片描述

连接层:最上层是一些客户端和链接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。
服务层:第二层架构主要完成大多数的核心服务功能,如QL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如 过程、函数等。
引擎层:存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过AP!和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。
存储层:主要是将数据存储在文件系统之上,并完成与存储引擎的交互。

1.1.2存储引擎简介

存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被称为表类型。

1.1.3示例语句

在这里插入图片描述

--查询建表语句	---默认存储引擎:InnoDB
show create table account;

在这里插入图片描述

--查询当前数据库支持的存储引擎
show engines;

在这里插入图片描述

--创建表 my_myisam ,并指定MYISAM存储引擎
create table my_myisam(
	id int,
	name varchar(10)
)engine = MyISAM;
--创建表 my_memory ,并指定Memory存储引擎
create table my_memory (
	id int,
	name varchar(10)
)engine = Memory;

1.2特点

1.2.1InnoDB

介绍
InnoDB是一种兼顾高可靠性和高性能的通用存储引擎,在 MVSOL5.5之后,InnoDB是默认的 MVSOL 存储引擎,
特点
DML操作遵循ACID模型,支持事务;
行级锁,提高并发访问性能;
支持 外键 FOREIGN KEY约束,保证数据的完整性和正确性。
文件
xxx.ibd:xxx代表的是表名,innoDB引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引。参数:innodb file per table

在这里插入图片描述

1.2.2MyISAM

介绍
MyISAM是MySQL早期的默认存储引擎。
特点
不支持事务,不支持外键
支持表锁,不支持行锁
访问速度快
文件
xxx.sdi:存储表结构信息
xxx.MYD:存储数据
xxx.MYI:存储索引
在这里插入图片描述

1.2.3Memory

介绍
Memory引擎的表数据时存储在内存中的,由于受到硬件问题、或断电问题的影响,只能将这些表作为临时表或缓存使用
特点
内存存放
hash索引(默认)
文件
xxx.sdi:存储表结构信息

1.2.4特点总结

在这里插入图片描述

1.3选择

在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组合。

  • InnoDB:是Mysql的默认存储引擎,支持事务、外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作,那么InnoDB存储引擎是比较合适的选择。
  • MyISAM: 如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常合适的。
  • MEMORY:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。

1.4总结

在这里插入图片描述

2.索引

2.1介绍

索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

演示
在这里插入图片描述
优缺点
在这里插入图片描述

2.2结构

MySOL的索引是在存储引擎层实现的,不同的存储引警有不同的结构,主要包含以下几种:
在这里插入图片描述
各数据库引擎对不同索引的支持情况:
在这里插入图片描述
我们平常所说的索引,如果没有特别指明,都是指B+树结构组织的索引。

2.2.1Btree

二叉树
在这里插入图片描述
二叉树缺点、顺序插入时,会形成一个链表,查询性能大大降低。大数据量情况下,层级较深,检索速度慢。

通过红黑树解决单向插入的问题
在这里插入图片描述
红黑树:大数据量情况下,层级较深,检索速度慢。

B-Tree(多路平衡查找树)
以一颗最大度数(max-degree)为5(5阶)的b-tree为例(每个节点最多存储4个key,5个指针):

在这里插入图片描述

知识小贴士: 树的度数指的是一个节点的子节点个数。

插入100 65 169 368 900 556 780 35 215 1200 234 888158 90 1000 88 120 268250 数据为例。
在这里插入图片描述
一个节点插入数超过4则五个数中间那个向上提升

2.2.2B+tree

以一颗最大度数(max-degree)为4(4阶)的b+tree为例:
在这里插入图片描述
插入100 65 169 368 900 556 780 35 215 1200 234 888 158 90 1000 88 120 268250 数据为例。
在这里插入图片描述
相对于B-Tree区别:

  • 所有的数据都会出现在叶子节点
  • 叶子节点形成一个单向链表

MVSOL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。(双向循环链表)
在这里插入图片描述
sql中存储数据为:表空间 段 区 页 行

2.2.3Hash

哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中
如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决。
在这里插入图片描述
Hash索引特点

  • Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,<,…)
  • 无法利用索引完成排序操作
  • 查询效率高,通常只需要一次检索就可以了(未产生hash碰撞的情况),效率通常要高于B+tree索引

存储引擎支持
在MVSQL中,支持hash索引的是Memory引擎,而innoD8中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构
建的。
innoD8中具有自适应hash功能:MySql根据查询条件,在指定的查询条件下自动的将B+Tree索引构建为Hash索引

2.3分类

在这里插入图片描述
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:
在这里插入图片描述
聚集索引选取规则:

  • 如果存在主键,主键索引就是聚集索引。
  • 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
  • 如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

在这里插入图片描述
回表查询

select*from user where name ='Arm';

在二级索引走一遍查询到id后再在聚集索引中查询id得到行数据
在这里插入图片描述

2.4语法

2.4.1语法

-- 创建索引
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name (index_col_name,...);

--查看索引
SHOW INDEX FROM table_name;

-- 删除索引
DROP INDEX index_name On table_name;

2.4.2案例

按照下列的需求,完成索引的创建

  • 1.name字段为姓名字段,该字段的值可能会重复,为该字段创建索引
  • 2.phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。
  • 3.为profession、age、status创建联合索引。
  • 4.为email建立合适的索引来提升查询效率
CREATE INDEX idx_user_name ON tb_user(name);
CREATE UNIQUE INDEX idx_user_phone ON tb_user(phone);
CREATE INDEX idx_user_pro_age_sta ON tb_user(profession,age,status);
CREATE INDEX idx_user_email ON tb_user(email);

DROP INDEX idx_user_email ON tb_user;--从tb_user表中删除idx_user_email索引

2.5性能分析

2.5.1SQL执行频率

MySQL 客户端连接成功后,通过 show[session|global] status命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的
INSERT、UPDATE、DELETE、SELECT的访问频次:

SHOW GLOBAL STATUS LIKE 'Com_______';--七个下划线

在这里插入图片描述

2.5.2慢查询日志

慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。
MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

#开启MySOL慢日志查询开关
slow query log=1
# 设置慢日志的时间为2秒,50l语句执行时间超过2秒,就会视为查询,记录慢查询日志
long_query tirme=2

配置完毕之后,通过以下指令重新启动MySQL服务器进行测试,查看慢日志文件中记录的信息/var/lib/mysql/localhost-slow.log.(linux中)
在这里插入图片描述
在这里插入图片描述

2.5.3profile详情

show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have profiling参数,能够看到当前MySQL是否支持
profile操作:

SELECT @@have_profiling;
#默认profiling是关闭的,可以通过set语句在session/global级别开启profiling:
SET profiling = 1;

在这里插入图片描述
默认profiling为未开启状态
在这里插入图片描述
开启profiling
在这里插入图片描述
设置为1后重新查看则开关已打开
在这里插入图片描述
执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:

#查看每一条SOL的耗时基本情况
show profiles;
#查看指定query id的SQL语句各个阶段的耗时情况
show profile for query query id;
#查看指定query id的SQL语句CPU的使用情况
show profile cpu for query query id;

在这里插入图片描述
在这里插入图片描述

2.5.4explain执行计划

EXPLAIN 或者 DESC命令获取 MVSOL如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。
语法:

#直接在select语句之前加上关键字explain/desc
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件;

EXPLAIN执行计划各字段含义:
id:

  • select查询的序列号,表示查询中执行select子句或者是操作表的顺序(id相同,执行顺序从上到下;id不同,值越大,越先执行)。

select_type:

  • 表示 SELECT的类型,常见的取值有 SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)
    UNION(UNION 中的第二个或者后面的查询语句)、SUBQUERY(SELECT/WHERE之后包含了子查询)等

type:

  • 表示连接类型,性能由好到差的连接类型为NYLL、system、const、eg ref、ref、range、index、all。(NULL即什么也不做)

possible_key:

  • 显示可能应用在这张表上的索引,一个或多个。

Key:

  • 实际使用的索引,如果为NULL,则没有使用索引。

Key len:

  • 表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。

rowS:

  • MySOL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的。

filtered:

  • 表示返回结果的行数占需读取行数的百分比,filtered 的值越大越好
    在这里插入图片描述
    在这里插入图片描述

2.6索引使用

2.6.1验证索引效率

在未建立索引之前,执行如下SOL语句,查看SOL的耗时。

SELECT*FROM tb sku WHEREsn='100000003145001';

针对字段创建索引

create index idx_sku_sn on tb sku(sn);

然后再次执行相同的SQL语句,再次查看SOL的耗时。

SELECT*FRGM tb sku WHERESn='100000003145001';

未创建索引前直接查询耗时较长
在这里插入图片描述
查看创建后的索引
在这里插入图片描述
创建索引后查询耗时大大缩短
在这里插入图片描述

2.6.2索引使用原则

最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是査询从索引的最左列开始,并且不跳过索引中的列。
如果跳跃某一列,索引将部分失效(后面的字段索引失效)。

explain select * from tb user where profession ='软件工程' and age = 31 and status = '0';
explain select * from tb user where profession ='软件工程' and age = 31;
explain select * from tb_user where profession ='软件工程';
explain select * from tb user where age = 3l and status = '0';
explain select * from tb user where status ='0';

在这里插入图片描述
不满足最左前缀法则,所以索引并未生效
在这里插入图片描述
status部分失效
在这里插入图片描述
优化器自动重排,所以顺序不对也可以走索引
在这里插入图片描述

范围查询

联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效

explain select * from tb user where profession='软件工程'and age>30 and status='0';
explain select * from tb user where profession ='软件工程'and age >= 30 and status ='0';

使用>时,age后的status没有走索引
使用>=时,age后的status走索引
语句中的顺序无关,只与索引实际顺序有关
在这里插入图片描述

索引列运算

不要在索引列上进行运算操作,索引将失效

explain select *from tb user where substring(phone,10,2)='15';

在这里插入图片描述

字符串不加引号

字符串类型字段使用时,不加引号,要索引将失效

explain select * from tb user where profession="软件工程' and age = 31 and status = 0;
explain select * from tb userwhere phone=17799990015;

索引生效,符合最左前缀法则
在这里插入图片描述
status值未加引号status未走索引
在这里插入图片描述

模糊查询

如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。

尾部模糊匹配,索引生效
在这里插入图片描述
头部模糊匹配,索引失效
在这里插入图片描述
前后都有也失效,只要前加了就失效
在这里插入图片描述

or连接的条件

用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。

explain select * from tb user where id 10 or age = 23;
explain select * from tb user where phone ='17799990017' or age = 23;

由于age没有索引,所以即使id、phone有索引,索引也会失效。所以需要针对于age也要建立索引。

数据分布影响

如果MySQL评估使用索引比全表更慢,则不使用索引。

select * from tb user where phone >='17799990005';
select * from tb user where phone >='17799990015';
SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
use index:
建议使用索引,mysql评估后可能不接受建议

explain select * from tb user use index(idx user pro) where profession='软件工程';

ignore index:
忽略用某个索引

explain select * from tb_userignore index(idx user pro) where profession='软件工程';

force index:
强制使用所以

explain select * from tb user force index(idx user pro) where profession ='软件工程';
覆盖索引

尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select*。

explain select id, profession from tb user where profession='软件工程' and age= 31 and stalus='0';
explain select id,profession,age, status from tb user where profession='软件工程'and age = 31 and status = '0' ;
explain select id,profession,age, slalus, name from tb user where prolession ='软件工程'and age = 31 and slalus = '0';
explain select * from tb user where profession='软件工程' and age = 3l and status = '0';

在这里插入图片描述
在这里插入图片描述
第三条为回表查询,先在辅助索引中查找到name,但没有gender信息,所以需要id去做聚集索引
第二条为覆盖索引,因为辅助索引中直接取得需要的id和name信息一步到位
使用select*极易产生回表查询

前缀索引

当字段类型为字符串(varchar,text等),时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

create index idx_xxx on table name(column(n));

前缀长度
可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

create index idx_email_5 on tb_user(email(5));
select count(distinct email) / count(*) from tb user ;
select count(distinct substring(email,1,5))/ count(*)from tb user ;

在这里插入图片描述

单列索引和联合索引

单列索引:即一个索引只包含单个列。
联合索引:即一个索引包含了多个列。
在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。

单列索引,可能用到idx_user_phone与idx_user_name,实际上sql选择用到udx_user_phone
在这里插入图片描述

多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询。
在这里插入图片描述
创建联合索引
在这里插入图片描述
使用查询,可能用到idx_user_phone与idx_user_name与联合索引,但实际sql选择phone的索引
在这里插入图片描述
提示sql使用联合索引
在这里插入图片描述
在这里插入图片描述

2.7索引设计原则

  • 1.针对于数据量较大,且查询比较频繁的表建立索引。
  • 2.针对于常作为查询条件(where)、排序(orderby)、分组(groupby)操作的字段建立索引。
  • 3.尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  • 4.如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
  • 5.尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
  • 6.要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
  • 7.如果索引列不能存储NULL值,请在创建表时使用NOTNULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

2.8思考

为什么InnoDB存储引擎选择使用B+tree索引结构?

  • 相对于二叉树,层级更少,搜索效率高
  • 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;
  • 相对Hash索引,B+tree支持范围匹配及排序操作

以下SQL语句哪个查询效率高

select *from user wher id=10;
select*from user where name='Arm';
-- 备注: id为主键,name字段创建的有索引;

在这里插入图片描述
第一条查询的效率高于第二条,第二条为回表查询

InnoDB主键索引的B+tree高度为多高呢?
假设:
一行数据大小为1k,一页中可以存储16行这样的数据。InnoDB的指针占用6个字节的空间,主键即使为bigint,占用字节数为8。
高度为2:
n8+(n+1)6=161024,算出n约为 1170
1171
16=18736
高度为3:
1171117116=21939856
在这里插入图片描述
一张表,有四个字段(id,username,password,status)由于数据量大,需要对以下SQL语句进行优化,该如何进
行才是最优方案:

select id,username,password from tb user where username = 'itcast';

最佳方案是针对username和password组建联合索引,则不需要回表查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值