mysql高级知识点

一、mysql架构

  1. 连接层:负责接收客户端的连接请求,可以进行授权、认证(验证账号密码)。
  2. 服务层:负责调用sql接口,对sql语法进行解析,对查询进行优化,缓存。
  3. 引擎层:是真正进行执行sql的地方,不同的引擎特点不同。
  4. 物理文件存储层:使用各种文件以及各种日志文件来存储数据。

与数据库交互一次:首先通过语言向数据库发送SQL,SQL经过服务层经过一系列处理,然后到达引擎层,选择不同的引擎进行处理,最后将数据存储在文件或者日志中。

二、mysql引擎

引擎:对数据处理的不同的方式(锁的方式、事物方式)。mysql中提供了多种不同的引擎,在实际的开发中,可以根据需要选择不同的引擎,这样会提高灵活度。

1、查看数据库支持的所有引擎 show engines;

2、查看表的引擎 show table status like 'user';

3、修改引擎

方式1:将 mysql.ini 中 default-storage-engine=InnoDB,重启服务.

方式2:创建表时指定引擎

create table user(
	id int,
	account int
)engine=myisam;

 方式3:修改表的引擎

alter table 表名 engine = INNODB; 

存储引擎主要有:MyIsam,InnoDB,Memory,Blackhole,CSV,Performance_Schema,Archive,Federated,Mrg_Myisam(innodb是唯一一个支持事物的引擎)

主要分析InnoDB和MyIsam:

对比项Innodb(默认)MyISAM
事务支持不支持
强外键约束支持不支持
缓存缓存索引,还缓存真实数据只缓存索引,不缓存真实数据
行级锁(对某行数据操作时,只会锁定某一行数据,效率高)表锁(进行增删改操作时,会锁定整张表,效率低)
主要适用于增删改多的场景查询多的场景
存储表的总行数不支持支持
表空间
关注点事务性能

三、索引

为什么要用到索引?数据量大的时候,需要查询一个数据,效率非常低。因为要从第一个开始进行查找,直到找到数据为止。

索引是一种有序的数据结构,利用索引可以提高mysql的查询效率。类似于书的目录,不需要翻遍每一页去查询数据,可以通过目录快速定位获取。创建数据库表的时候,会为一些列创建索引,这样查询效率高。

本质都是:通过不断地缩小范围,来获取数据,同时把随机的事件变成顺序的事件。

为了加快col2的查找,给col2创建索引,就会给col2列创建一个二叉树。

优势:提高查询效率,体现在与硬盘IO次数减少了;由于是排好序的,降低了查询次数,cpu消耗低。

劣势:实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。所以索引需要存储空间;新增、修改、删除操作时也需要维护索引需要的时间开销。

1、索引创建原则

哪些情况需要创建索引:

  • 主键会自动创建唯一的索引
  • 查询条件的列(where后面的语句),加快条件的判断速度。
  • 外键的列
  • 排序的列
  • 分组中的字段

哪些列不适合建立索引:

  • 表记录太少
  • 经常增删改的表(因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件)
  • Where条件里用不到的字段
  • 数据重复率高的列(例如性别:男、女)
2、索引分类

查看索引:show index from 表名;

1.主键索引:设定为主键后数据库会自动建立索引

alter table 表名 drop primary key;#删除主键(索引)
ALTER TABLE test add PRIMARY KEY test(id);#添加主键

2.单值索引:一个索引中只包含一个列,一个表可以有多个单列索引

创建单值索引:create index 索引名 on 表名(列名);

删除索引:alter table 表名 drop index 索引名;

create index index_student_name on student(name);#创建单值索引
explain select * from student where name="张三" #测试
alter table student drop index index_student_name;#删除索引

3.唯一索引:索引列的值必须唯一,允许为null

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

4.组合索引(复合索引):一个索引中可以包含多个列。组合索引比单值索引的开销小

创建复合索引:create index 索引名 on 表名(列 1,列 2...);

删除索引:alter table 表名 drop index 索引名;

create index index_student_name_gender on student(name,gender);#创建

组合索引要满足最左前缀原则:

例如表中有a、b、c 3列,a、b两列创建组合索引。当查询条件中用到组合索引时,必须使用到最左边列,否则索引失效。

create index index_test_a_b on test(a,b); #a列就是最左边列
explain select * from test where a = 'aa' and b='bb'
explain select * from test where b = 'aa' and a='bb'
explain select * from test where a = 'aa' and c='bb'

explain select * from test where b = 'aa' and c='bb' -- 组合索引失效 因为没有用到最左边列

 5.全文索引:可以解决模糊查询索引失效的问题。(模糊查询时,索引会失效。)

explain select * from test where name like '%j%'#模糊查询时,索引失效

create fulltext index 索引名 on 表名(字段名) with parser ngram;

select 结果 from 表名 where match(列名) against('搜索词')

create fulltext index index_content ON test(content) with parser ngram;#test表中,content列创建了全文索引
 
explain select * from  test where MATCH(content) against('中国')#content列中有没有出现“中国”
3、索引的数据结构

二叉树、红黑树在自增主键中使用,效率不高。

使用B+树:

  • 排好序的,一个节点可以存储多个数据,使得B+树的高度不会太高。
  • 数据存储在叶子节点,叶子节点之间还有连接
  • 非叶子节点只存储索引,可以放更多的索引。

4、聚簇索引和非聚簇索引

聚簇索引:找到了索引就找到了数据。innodb中的主键索引就是聚簇索引,主键索引的B+树的叶子节点存储的就是数据。

一个表生成的数据、索引、表结构都存储在.ibd文件中,因为数据和主键的索引树绑在一起的。

 innodb中除了主键索引是聚簇索引,其他索引是非聚簇索引。例如name列添加了索引,但是不能直接通过name找到数据,先通过name索引树找到主键索引,再通过主键找到数据,需要两次查找,所以是非聚簇索引。

非聚簇索引:找到了索引,并没有找到数据,需要二次查询。myisam引擎中的索引都是非聚簇索引,因为表结构、索引、数据都在不同的表中存储。  

5、回表查询

回表查询也就是二次查询。例如通过学号/姓名等信息作为条件查询,首先通过学号/姓名找到主键索引,再通过主键索引找到数据,称为回表查询。

例如:学生表

id 主键索引

no 唯一索引

name 单值索引

如果我们通过主键查询学生信息,因为主键索引是聚簇索引,找到主键索引就找到了数据,所以不需要回表查询。

select * FROM student WHERE id = 1

 如果通过学号去查询学号和姓名,因为学号是非聚簇索引,通过学号找到主键索引,再通过主键索引找到学号和姓名,需要二次回表查询。

SELECT NO,NAME FROM student WHERE NO = 123

如果通过学号只查询学号是否存在,找到学号索引,就找到了数据,此种场景不需要再回表查询了,也属于聚簇索引。

SELECT NO FROM student WHERE NO = 123

四、锁机制

多个事物(线程)对同一个表中的同一行数据进行操作,需要通过锁进行保护。按照粒度,锁可以分为表锁、行锁、间隙锁。innodb引擎支持行级锁,可以将锁的粒度到行级。

表锁:操作时会锁住整张表,效率低。myisam就只支持表锁。

行锁:操作时会锁住操作的行,并发量高。innodb支持支持表锁和行锁,且出于性能考虑,绝大多数情况下使用的都是行锁

间隙锁:当条件为一个范围区间时,只对某个区间进行加锁。innodb支持间隙锁。

共享锁(S):又称读锁。一个事物对数据A进行读操作时,如果添加了共享锁,其他事物可以对数据A进行读操作,但是其他事物就不能对数据A进行修改,不能加排他锁。添加共享锁语法:select … lock in share mode;

排他锁(X):又称写锁。事物A对数据进行增删改操作时,会自动添加锁,其他事物不能对数据加任何锁,直到事物A释放锁才可以。增删改会自动加锁;查询时如果需要添加排他锁,可以使用select … for update;语句。

五、事务

mybatis中提交事物,sqlsession.commit();

spring对事物进行管理:编程式事物、声明式事物(xml配置, 注解)

事物:数据库操作的过程中可能包含多条sql执行,多条sql执行应该是一个整体,保多条sql语句要么全部执行, 要么全部不执行。 用来管理insert、update、delete语句。

mysql中只有innodb引擎支持事物

1、事物特征(ACID)

原子性(Atomicity):一个事物中有多条sql,要么都成功执行,要么都不执行,执行过程中如果发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。

持久性(Durability):在事物提交后,要保证数据的持久化。

隔离性(Isolation):在多个事物并发访问下,对多个事物操作要进行隔离,各个事务之间不能互相干扰。

一致性(Consistency):最终目标就是保证数据操作的一致性。例如经过多次转账操作后,最终的结果和预期的结果应该一致。

2、事务设置

默认情况下,MySQL启用自动提交模式(变量autocommit为on)。只要执行DML操作的语句,MySQL会立即隐式提交事务。

用SET来改变MySQL的自动提交模式

SET GLOBAL autocommit=0; #禁止自动提交 
SET GLOBAL autocommit=1;#开启自动提交 

查看autocommit模式

SHOW GLOBAL VARIABLES LIKE 'autocommit';

例如:

begin;/START TRANSACTION;#开始一个事务
	insert into test(id,name) value(2,'aaa');
commit#事务确认

rollback#事务回滚
3、事务隔离级别

只有InnoDB支持事务,所以这里说的事务隔离级别是指InnoDB下的事务隔离级别。

理论上在某个事务对数据进行操作时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续操作这个数据。但是这样的话对性能影响太大,所以设计数据库的大叔提出了各种隔离级别,来最大限度的提升系统并发处理事务的能力。

查看隔离级别:SELECT @@global.transaction_isolation,@@transaction_isolation;

设置隔离级别:SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

多个事物对同一个数据操作时,采用哪种隔离级别。mysql中默认的隔离级别是可重复读。

4种隔离级别:

1.读 未提交(read uncommitted):A事物正在对数据操作,事物没有提交,此时B事物可以读到A事物修改后未提交的数据。可能出现的问题:脏读、不可重复读、幻读。

2.读 已提交(read committed):A事物对数据正在操作,B事物只能读到A事物已经提交的数据,如果未提交,是读不到的。解决了脏读问题,但是仍然有 不可重复读、幻读问题。

3.可重复 读(repeatable read):事物B在事物A中连续读取同一个数据,两次读到结果是一致的,哪怕在此期间有别的事物修改数据。解决了 不可重读问题。

mysql8中的可重读的正常查询解决了幻读问题,如果在查询语句后面添加for update语句,会出现幻读问题。

4.串行化(serializable):当一个事物对一行进行操作时(即使是读操作),还未提交,其他事物不能进行增删改操作。

脏读:B事务读取A事务中的数据,但A事物有可能回滚,B事物读到的就是脏数据。

不可重复读:在同一个事物中,两次读同一个id的数据不相同的。(事务A将数据改了,事务B读不到,只能读到和之前一样的????)

幻读:在一个事物,两次读到数量不一致。(事务A新增了一条数据,事务B读不到,只能读到和之前一样的????)

4、事物实现原理(和增删改相关的)
1.原子性原理

在底层使用undolog(回滚日志)日志,保存一个相反的操作。例如执行insert操作,那么undolog日志中会记录一个相反的delete操作;执行delete操作,记录一个insert,当事物回滚时,执行反向操作。

2.持久性实现原理

使用redolog(重做日志)保证持久性。执行sql时,先将sql写入到redolog中,然后再执行保存到数据库;万一这个过程中,数据还没有写入到硬盘,突然断电,那么下次mysql启动时,会重新执行redolog日志,保证持久性。

3.隔离性

多版本并发控制(MVCC Multi-Version Concurrent Control)

为了实现可重复读,底层每次事物操作时,都会生成一个版本,对于数据的多个操作,每个版本之间都存在关系,形成一个版本链

如果是读已提交,每次会生成一个最新的版本快照,读到最新提交的数据。

如果是可重复读,会在第一次读的时候生成一个版本快照,之后再次读取时,仍然从第一次生成的快照中读。

4.一致性

通过满足原子性、持久性、隔离性,最终达到一致性。

SQL优化

1. 使用varchar代替char
  • varchar:字符串长度不固定时使用,按数据的实际长度存储,可以节省存储空间; 如:姓名,地址,QQ号
  • char:字符串长度固定时使用,不足补空格; 如:性别,手机号

1)char定长字符串, 不足的会以空格补齐,最多可以存储255个字符

2)varchar变长字符串,有几个字符就存储几个字符,最多可以存储65535个字符

2. 清空表时优先使用truncate

(一张表里有100万条数据,需要清空,怎么做?)

truncate table比delete速度快,且使用的系统和事务日志资源少。

delete 语句每次删除一行,并在事务日志中为所删除的每行记录一项。truncate table 通过释放存储表数据所用的数据页来删除数据

delete是一行一行删的

truncate是DDL语句,对表结构操作的

3.查询SQL尽量不要使用select *,而是具体字段

节省资源、减少网络开销。

可能用到覆盖索引,减少回表,提高查询效率。

4.表连接不宜太多,索引不宜太多,一般5个以内

联的表个数越多,编译的时间和开销也就越大

每次关联内存中都生成一个临时表

应该把连接表拆开成较小的几个执行,可读性更高

5. 尽量使用数值替代字符串类型

主键(id):primary key优先使用数值类型int

性别(sex):0代表女,1代表男;数据库没有布尔类型,mysql推荐使用tinyint

因为引擎在处理查询和连接时会逐个比较字符串中每一个字符;而对于数字型而言只需要比较一次就够了;

字符会降低查询和连接的性能,并会增加存储开销;

6. 提高 group by 语句的效率

反例:先分组,再过滤

正例:先过滤,后分组

7. inner join 、left join、right join,优先使用inner join

三种连接如果结果相同,优先使用 inner join

inner join 内连接,只保留两张表中完全匹配的结果集;

left join 会返回左表所有的行,即使在右表中没有匹配的记录;

right join 会返回右表所有的行,即使在左表中没有匹配的记录;

8.首先考虑在where及 order by涉及的列上建立索引
9.避免在where子句中使用or来连接条件

反例:SELECT * FROM user WHERE id=1 OR salary=5000

正例:使用union all把两个两个SQL结果合并

对于or没有索引的salary这种情况,假设它走了id的索引,但是走到salary查询条件时,它还得全表扫描;

10. 避免在索引列上使用内置函数,索引失效
11. 避免索引失效

1. 模糊查询将导致全表扫描(两边都有%)

select id from t where name like '%abc%'

2. 避免在where子句中使用or来连接条件,否则导致索引失效,而进行全表扫描,如:select id from t where num=10 or num=20

3. in和not in要慎用,否则会导致全表扫描,如:select id from t where num in(1,2,3),对于连续的数值,能用between就不用in,因为B+树中,叶子节点之间有联系,范围查找快一些。select id from t where num between 1 and 3

4. 避免where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where substring(name,1,3)='abc'

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/190524.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

类与对象——(1)初识对象——C++中的string

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 或许不安或许迷惑,但…

storyBook常见踩坑报错 和 解决

用StoryBook官网的代码&#xff0c;但报错&#xff0c;Unexpected token’<’ 在js文件中// Button.stories.js|jsx import { Button } from ‘./Button’; export default { component: Button, }; /* *&#x1f447; Render functions are a framework specific featur…

Liunx系统使用超详细(一)

目录 一、Liunx系统的认识 二、Liunx和Windows区别 三、Liunx命令提示符介绍 四、Liunx目录结构 一、Liunx系统的认识 Linux系统是一种开源的、类Unix操作系统内核的实现&#xff0c;它基于Unix的设计原理和思想&#xff0c;并在全球范围内广泛应用。以下是对Linux系统的详…

文件的写入和读取操作

题目&#xff1a; 编写一个程序&#xff0c;实现以下功能&#xff1a; 1. 创建一个新的文本文件&#xff0c;并将用户输入的数据写入文件中。 2. 打开已存在的文本文件&#xff0c;并将其中的数据显示在屏幕上。 #include <stdio.h> #include <stdlib.h> void wri…

一文讲明SpringMVC 【爆肝整理一万五千字】

我 | 在这里 &#x1f575;️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 &#x1f3e0; 工作 | 广州 ⭐ Java 全栈开发&#xff08;软件工程师&#xff09; &#x1f383; 爱好 | 研究技术、旅游、阅读、运动、喜欢流行歌曲 ✈️已经旅游的地点 | 新疆-乌鲁木齐、新疆-吐鲁番、广东-广州…

【JVM系列】- 穿插·对象的实例化与直接内存

对象的实例化与直接内存 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录…

Java多线程二-线程安全

1、线程安全问题 多个线程&#xff0c;同时操作同一个共享资源的时候&#xff0c;可能会出现业务安全问题。 2、实例&#xff1a;取钱的线程安全问题 2.1、场景 小明和小红是夫妻&#xff0c;他们有个共同账户&#xff0c;余额是十万元&#xff0c;如果两人同时取钱并且各自取…

Nodejs 第二十章(fs 上)

概述 在 Node.js 中&#xff0c;fs 模块是文件系统模块&#xff08;File System module&#xff09;的缩写&#xff0c;它提供了与文件系统进行交互的各种功能。通过 fs 模块&#xff0c;你可以执行诸如读取文件、写入文件、更改文件权限、创建目录等操作&#xff0c;Node.js …

Mindomo Desktop for Mac免费思维导图软件,助您高效整理思维

思维导图是一种强大的工具&#xff0c;可以帮助我们整理思维、提高记忆力、激发创造力。而Mindomo Desktop for Mac作为一款免费的思维导图软件&#xff0c;能够帮助我们更高效地进行思维整理和项目管理。在本文中&#xff0c;我们将介绍Mindomo Desktop for Mac的功能和优势&a…

汽车租聘管理与推荐系统Python+Django网页界面+协同过滤推荐算法

一、介绍 汽车租聘管理与推荐系统。本系统使用Python作为主要编程语言&#xff0c;前端采用HTML、CSS、BootStrap等技术搭建前端界面&#xff0c;后端采用Django框架处理用户的请求。创新点&#xff1a;使用协同过滤推荐算法实现对当前用户个性化推荐。 其主要功能如下&#x…

频剪辑软件Corel VideoStudio 会声会影2024最新7大新全新功能解析

我很喜欢视频剪辑软件Corel VideoStudio 会声会影2024&#xff0c;因为它使用起来很有趣。它很容易使用&#xff0c;但仍然给你很多功能和力量。视频剪辑软件Corel VideoStudio 会声会影2023让我与世界分享我的想法&#xff01;“这个产品的功能非常多&#xff0c;我几乎没有触…

docker介绍、部署与常用命令

一、docker 介绍 1、容器&#xff08;Container&#xff09;&#xff1a; (1) 概念&#xff1a; 容器是一种用于运行和部署应用程序的技术。它将应用程序及其所有依赖项&#xff08;例如代码、运行时、系统工具、系统库等&#xff09;打包在一个独立的、可移植的运行环境中&…

[C++]指针与结构体

标题 一.指针1.指针的定义和使用2.指针所占的内存空间3.空指针与野指针4.const修饰指针5.指针和数组6.指针和函数 二.结构体1.结构体的定义与使用2.结构体数组3.结构体指针4.结构体的嵌套使用5.结构体做函数参数6.结构体中const使用场景7.案例练习 一.指针 作用: 可以通过指针…

SpringBoot 拦截器高级篇

Springboot 拦截器 定义使用场景拦截器与过滤器的区别实现步骤全局拦截器的局限性全局拦截器VS局部拦截器局部拦截器自定义局部拦截器使用多个局部拦截器 定义 拦截器是Spring MVC框架中的一个重要组件&#xff0c;它是一种AOP&#xff08;面向切面编程&#xff09;的实现方式&…

文本编辑 UTF-8 BOM 中的BOM释义

参考资料 UTF8のBOM無しとBOM付きの違いBOMなしUTF-8によってWindowsでもたらされる困惑文字コードをUTF-8 BOMなし(UTF-8N)でファイル保存をする方法 目录 一. 前提二. BOM三. CSV文件中的表现 一. 前提 在使用Windows自带的记事本编辑.csv文件的时候&#xff0c;准备保存为…

Linux安装jdk8【十分丝滑】

1.上传安装包到Linux&#x1f495;&#x1f495;&#x1f495; 2.使用命令解压缩&#x1f495;&#x1f495;&#x1f495; tar -zxvf 压缩文件名 3.重命名&#x1f495;&#x1f495;&#x1f495; mv 原文件名 新的文件名 4.配置环境变量&#x1f929;&#x1f929;&…

Labelme加载AI(Segment-Anything)模型进行图像标注

labelme是使用python写的基于QT的跨平台图像标注工具&#xff0c;可用来标注分类、检测、分割、关键点等常见的视觉任务&#xff0c;支持VOC格式和COCO等的导出&#xff0c;代码简单易读&#xff0c;是非常利用上手的良心工具。 第一步&#xff1a;   下载源码进行安装。 g…

PaddleOCR学习笔记

Paddle 功能特性 PP-OCR系列模型列表 https://github.com/PaddlePaddle/PaddleOCR#%EF%B8%8F-pp-ocr%E7%B3%BB%E5%88%97%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8%E6%9B%B4%E6%96%B0%E4%B8%AD PP-OCR系列模型列表&#xff08;V4&#xff0c;2023年8月1日更新&#xff09; 配置文…

Spring如何在多线程下保持事务的一致性

Spring如何在多线程下保持事务的一致性 方法&#xff1a;每个线程都开启各自的事务去执行相关业务&#xff0c;等待所有线程的业务执行完成&#xff0c;统一提交或回滚。 下面我们通过具体的案例来演示Spring如何在多线程下保持事务的一致性。 1、项目结构 2、数据库SQL CR…

Unity 场景切换

Unity场景切换可使用以下方法&#xff1a; 1、SceneManager.LoadScene()方法&#xff1a; using UnityEngine.SceneManagement;// 切换到Scene2场景 SceneManager.LoadScene("Scene2"); 2、使用SceneManager.LoadSceneAsync()方法异步加载场景&#xff0c;异步加载…