没有理想的人不伤心

MySQL 基础

2025/10/26
5
0

image.png

SQL

sql 语句不区分大小写,关键字建议使用大写

一条 sql 语句以分号结尾

注释:

  • 单行:-- 或 #
  • 多行:/* */

sql 分类:

1731141364685-f5c2b59a-9329-46d5-a9ea-d416eae85a46.png

数据类型

  • 数值类型
  • 字符串类型

1731144428088-7441c12e-e11a-44e5-89d2-a8a2d998e107-211998.png

1731144908437-19ecdee0-0749-4ade-8dda-27acd2a58080.png

1731145098177-84dd46b1-bb31-45bc-bf0c-f04f66b8f325.png

DDL

  1. 对数据库的操作

1731141561758-90e22aa8-ce24-4c2c-a657-25ed607e0d71.png

  1. 表操作

查询当前数据库中的所有表:show tables;

查询表结构: desc 表名;

查询指定表的建表语句: show create table 表名;

创建表:create table

1731143058697-a5400961-828d-4363-a987-272b8968ff0e.png

表修改:alter

添加字段:1731145776438-79fcfcdd-e8e0-4375-9447-3814f4f5d5d4.png

修改字段:

  • 只修改字段类型:

1731150361433-0bf394ea-0924-4c76-b511-a6d98da9ce33.png

  • 修改字段名和字段类型

1731150407635-2ce6722b-3e62-4889-85a4-60a301b12752.png

删除字段:

1731150613723-48505cf3-d2ea-422a-82b2-3408dc69b5f5.png

修改表名:

1731150874994-a3761036-a47d-4b10-b231-584ca6daafe5.png

删除表:

1731151017232-af4eeb03-f5d7-4d60-a0d8-d8a637ee15ca.png

删除表并重新创建该表

1731151024845-33b2c134-8a0b-4a9c-b6dc-137644fe128b.png

DML

增删改 insert delete update

  1. 插入数据

1731153042696-4753ae9d-3030-4ed0-ba11-176dd80848a4.png

  1. 修改数据

1731153505177-b185c1cd-80a8-4f23-87c6-18eb46b930a5.png

如果没有 where 条件,则会修改整张表的数据

  1. 删除数据

1731153798935-f22643c9-9332-446b-9d9e-160f7f581f05.png

如果没写 where 条件,就会删除表中所有数据

delete 不能用于删除某行某个字段的数据,只能删除行

DQL

select

编写顺序:

1731156488340-f6ee2208-35ae-4082-8fb7-bf0a165563bc.png

执行顺序:from -> where -> group by -> select -> order by -> limit

  • 基本查询

查询多个字段

1731156745180-19751ffc-5bb5-4d05-89dd-31fcb615a66b.png

设置字段别名

1731156763310-c337691b-2307-45bc-920b-99f9e5c4b2e4.png

去除重复记录

1731156792500-6483b626-57a1-4f87-a12a-7bf306929d9f.png

  • 条件查询(where)

1731157480025-a42e5e59-20e9-4c83-b651-3379e5e55337.png

1731157616456-ed14192f-2eb8-48ee-9ec6-6c3ac3482f02.png

1731157625884-4f52ebe8-fabb-4ef4-b230-504199298637.png

  • 聚合函数(count、max、min、avg、sum)

1731158259455-a42d71b1-5216-40a9-bc3b-f2e645bf2168.png

count:统计数量

max:最大值

min:最小值

avg:平均值

sum:求和

注:所有 NULL 值不参与聚合函数的运算

  • 分组函数(group by)

1731159312498-b3325fd6-dfdb-4834-aafa-6955fbad5e5a.png

分组查询返回的字段一般是分组的字段以及聚合函数

where 和 having 条件的区别:

执行时机不同,where 分组前过滤,having 分组后过滤

where 不能使用聚合函数进行判断,而 having 可以

  • 排序查询(order by)

1731160009101-39f19a20-71f7-460b-9acb-e7be35c8a35e.png

排序方式:asc(升序,默认值)、desc(降序)

对多个字段进行排序,先按第一个字段进行排序,如果有相同的,再按第二个字段,以此类推

  • 分页查询(limit)

1731160450796-cbb12669-750a-44be-a670-44339bfb4b74.png

索引和数组索引一样,是从 0 开始的,索引的计算也相同

不同数据库使用的关键字不相同

若起始索引是 0,可以省略

DCL

用户管理

  1. 查询用户

1731210087150-f618628b-695f-4a88-927e-e851161c988f.png

用户信息存放在 mysql 数据库的 user 表中

  1. 创建用户

1731210324142-272e0774-e2fa-4105-9b41-7746185b2401.png

主机名指的是在哪个主机上可以以此用户的身份对数据库进行访问

可以使用通配符 % 来表示任意主机

此时该用户没有任何权限

  1. 修改用户密码

1731210759202-a0ac8aea-0c16-425f-a21f-1476aa543d6f.png

  1. 删除用户

1731210958708-2ce817a0-b85f-4e16-b436-1897b287b8f7.png

权限控制

权限如下:

1731211235363-8aa3e96b-16ce-4c37-b961-ea075b733053.png

  1. 查询权限

1731211328217-b3963c17-240b-4542-85fd-feab6d26b418.png

  1. 授权

1731211488295-2e7c9582-574f-4845-a70b-c138126c6886.png

可以使用 * 来表示所有数据库名或表名,即 *.* 表示所有数据库和表

  1. 撤销权限

1731211595093-25ba24da-9d1f-419e-997f-0e8e79db705b.png

若要授予所有权限,那么权限列表填 all 就行

多个权限之间用逗号隔开

函数

字符串函数

1731212621468-fcf987f1-bff2-4da5-a9dd-11db4a525579.png

数值函数

1731213065059-1a64e0ec-27ac-421e-b09f-6c30e810c8af.png

日期函数

1731213380857-7c185c7a-7789-4b33-a277-bc75ccea1095.png

type 是时间单位 day、month、year

流程控制函数

1731214189934-d936b509-b97f-4c4c-827a-3305c44b9ae1.png

可以跟多个 when

1731214419027-8fc394e8-d5db-4911-86b7-1c2f9aae1887.png

1731214602345-43fcdc4d-caac-424f-94c2-df2a504ac562.png

约束

约束:作用于表中字段上的规则,用于限制存储在表中的数据

保证数据的正确性、有效性和完整性

1731215521965-4d0ecb88-804b-4941-9a4a-38bd374aeca9.png

可以在创建表或修改表的时候添加约束

如:

1731216700839-54867def-f45b-40c3-99f8-a14aa1ad8a94.png

1731216854642-571f1a53-1268-46ce-b0bf-83d1a3e3a48a.png

外键约束:

将具有外键的表称为子表,外键所关联的表称为父表

添加外键:

1731217395974-4102f162-4b34-4977-a504-7605adefa272.png

如:1731217480995-9e50fce6-3caa-4ad9-9d4e-16f8ddfefbf5.png

删除外键:

1731217562347-34f833cc-abf4-414f-998f-9b11ee8f333e.png

外键约束字段在删除、更新数据时的行为:(no action 和 restrict 是默认行为)

1731217689350-f7f4f877-edfd-45e7-acde-467d9d438eaf.png

1731217834629-ddd56ce6-49df-4fd9-ae65-14663f672c40.png

多表查询

多表关系

  1. 一对多

比如部门表和员工表之间,一个部门有很多员工,通常通过在多的表中(员工表)设置外键

  1. 多对对

比如学生和选课表之间的关系,一个学生可以选多门课,而一门课可以被多个学生选择,要记录这种关系,需要建立第三张中间表,至少包含两个外键,分别关联学生表和课程表的主键

  1. 一对一

如用户和用户信息之间的关系

一对一的关系多用于单表拆分,将基础字段放在一张表,详细信息字段放在另一张表,可以提升操作效率

如何维护两者之间的关系:在任意一张表加外键,关联另外一张表的主键,并将外键设置为 unique

多表查询的分类

1731220155496-6b91fe0b-ff48-4296-8831-b66de492c989.png

内连接查询——查交集

  • 显式内连接

1731220284397-9e8c7025-81c8-4b0a-abb7-36c4eccc7ef9.png

  • 隐式内连接

1731220292275-10f86ed6-b509-4e31-a5ec-04a1d20e1705.png

如:

1731220458931-2890088b-8ea3-4463-9bef-6d065a6d6078.png

1731220547834-9fdc2284-3c75-4c3f-9861-c926b0fc52d5.png

外连接查询

  • 左外连接

1731221324082-d2d4a507-0a5f-4cf4-bac8-c1ddf59a65d8.png

查 表 1 所有 + 表 1、2 交集部分数据

  • 右外连接

1731221447377-5a766039-dbe9-48a1-aa91-2be8eeda6f40.png

查 表 2 所有 + 表 1、2 交集部分数据

如:

1731221609654-254cb771-3027-4b77-80a5-bc527d7ebd80.png

左外和右外可以转化,交换表顺序就行,一般使用左外就行

自连接查询

1731222114164-2b44b72d-1d49-4a7c-87d5-b450434c9c5d.png

自连接可以是内连接查询也可以是外连接查询

必须给表起别名,把一张表看作两张表

通常用于一张表中的两字段有对应关系,如员工对应领导

如:

内连接

1731222877932-f9e3b8e5-7414-4150-97f7-2e7c738fcc82.png

左外连接

1731223070122-75d46f15-7e0c-49d4-96c0-fef1e3d2f042.png

联合查询-union

把多次查询的结果合并起来,形成一个新的查询结果集

1731223197432-eaef83d5-9899-4a9a-aaf2-0f9e4a7dc2e3.png

union all:直接将查询的结果合并(不去重)

union:将查询的结果合并后去重

联合查询的使用,查询的字段数以及字段数据类型必须相同

子查询(嵌套查询)

sql 语句嵌套 select

1731223575019-109838b6-357f-4403-b694-f017bb3829a3.png

外部语句可以是 insert update delete select 的任何一个

1731223663285-932c4e7c-6d9d-4d8f-950b-e6deebf823b7.png

根据子查询的位置,分为 where 之后、from 之后、select 之后

标量子查询

子查询返回的结果是单个值,即一行一列

常用操作符: = != <= >= < > 等

image.png
1731223957125-0425e13a-a1a1-4e7c-b78c-e56229de274b.png

列子查询

子查询返回结果是一列(不限制行数)

常用操作符:in、not in、any、some、all

1731224375457-38b9d543-afdc-43e6-814b-61ece87f2f13.png

如:

1731224463271-2f4afd6f-4fc9-497f-a770-c3033fbcd662.png

1731224569846-15de6025-293c-4f5d-a3ef-7c7174cffc25.png

1731227262586-3d4d8dd4-038c-46ed-9524-ddf4f6f905de.png

行子查询

返回结果是一行,可以是多列。

常用操作符:=、!=、in、not in

1731227535706-2d934017-de0e-4b30-ad4f-57f89ba610f9.png

表子查询

返回结果多行多列

一般用于将查询结果作为子表,然后在子表中查询

常用操作符:in

1731227725473-80a38710-21bd-4928-aa5b-45e5398dd0e8.png

1731227857923-61223941-f4df-4645-bc38-c38029e50ee3.png

事务

事务:一组操作的集合,事务会将所有操作视为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功要么同时失败

典型例子:转账问题

张三 --> 李四,先检查张三是否有 1000,若有,-1000,李四+1000

mysql 中的事务默认自动提交,即当执行一条 DML 语句时,mysql 会立即隐式的提交事务

因此需要手动的开启事务、提交事务以及回滚事务

事务操作

查看事务提交方式:

select @@autocommit

方式一:设置事务提交方式:

设置事务提交方式:0 为手动提交,默认 1 自动提交

set @@autocommit = 0

提交事务:

commit

回滚事务:

rollback

感觉像 git,执行事务只是保存到暂存区,只有 commit 后才放到本地仓库,且执行的结果不满意也可以进行 reset

方式二:开启事务

开启事务:

start transaction 或者 begin

提交:commit

回滚:rollback

事务的四大特性(ACID)-面试常问

1731236718646-af7982b5-b6c6-4d80-8b72-3335901cac94.png

并发事务问题

1731236923452-40dce9d3-3d6f-4a2f-95f6-4e3f7898fa09.png

事务隔离级别——解决并发事务问题

1731237283862-94616323-2528-4c57-be10-2b1e1f644762.png

查看事务隔离级别:

select @@transaction_isolation

设置事务隔离级别:

1731239126694-3a1c1fa0-1819-43d5-b58c-2a8e048c913d.png

session:仅针对当前会话有效

事务隔离级别越高,数据越安全,但是性能越低

mysql 体系结构

1731241298358-bfcaa8e5-6918-4028-969c-5f286c1174e0.png

1731241364438-8f657820-6684-4ffc-9a0b-6b124b7b0880.png

存储引擎

存储引擎:决定了存储数据、建立索引、更新/查询数据等技术的实现方式

存储引擎是基于表的,也就是不同表可以使用不同存储引擎,所以存储引擎也被称为表类型

在创建表时可以指定存储引擎

1731241684803-0005983a-f9f3-430c-9c5a-f0a381ce65c1.png

查看当前数据库支持的存储引擎

show engines

1731241804001-8d24fd25-9ae2-4e38-9e2e-5f3206e3d1cf.png

后面三个字段为:是否支持事务、是否只是 XA 协议、是否支持保持点

InnoDB

是一种兼顾高性能和高可靠性的存储引擎,在 MySQL5.5 后作为默认存储引擎

特点:支持事务、行级锁以及外键

文件存储:

文件名:表名.ibd

InnoDB 的每张表都会对应这样的一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引

innodb_file_per_table 该参数决定是否每个表空间都对应一个文件,一般默认每个都对应一个文件

frm 是早期的表结构存储,sdi 是后来的表结构存储

在 cmd 命令下行输入 idb2sdi 文件名,会显示一大串 json,其中是表结构

InnoDB 的逻辑存储结构

1731243579762-bc69cbf7-b792-4322-a19e-5a9d3ddbad4a.png

区(extent)的大小为 1MB,页(page)的大小为 16KB,一个区包含 64 个页

MyISAM

是 MySQL 早期的存储引擎

特点:不支持事务、不支持外键、不支持行级锁、支持表锁,访问速度快

文件存储:

1731243819250-eb245aab-7ac0-404c-91d6-64ee98a07978.png

Memory

表数据存储在内存中,只能作为临时表或缓存使用,因为断电数据会消失

特点:内存存放,读取快,支持 hash 索引

文件存储:xxx.sdi 存储表结构信息,因为数据都放在内存

三大存储引擎的区别——面试常问

1731244119002-b1687015-cb4a-47b7-a852-10e9a89e3fc4.png

特别是要清楚 InnoDBMyISAM 的三大区别:

InnoDB 支持事务、行锁和外键,而 MyISAM 都不支持,支持表锁

存储引擎的选择

1731244329816-3f0c3372-9cdd-46c6-a42c-bd26c0c2553e.png

绝大多数情况选择 InnoDB

而适合使用 MyISAM 的应用场景已经被 nosql 的 mongoDB 取代

适合 Memory 的应用场景被 redis 取代

索引(查询语句的优化)

索引是一种数据结构,用来高效获取数据

优点:

  • 提高查询效率,降低数据库的 IO 成本
  • 提高排序效率,降低 CPU 的消耗

缺点:

  • 索引列也占磁盘空间
  • 索引增加了查询效率,但是降低了表中数据的更新效率,降低增删改的效率。

缺点可以忽略,因为磁盘成本低,且正常业务系统应该是查询的次数远大于增删改

索引结构

mysql 的索引是在存储引擎层实现的,不同存储引擎具有不同的索引结构

1731333760828-36055463-537b-4dd5-a839-25a10569a5d6.png

1731333838049-032cffe4-fa4d-4e5c-8b75-02c642a5ef01.png

平时说的索引结构,一般只要没有特别指明,都是 B+树索引

B+树的特点:

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

1731379862746-d01effaf-7c51-4f5f-81e0-378a826a5936.png

mysql 索引结构对 B+树进行了优化,使得叶子节点形成双向链表

数据存储在叶子节点,其他节点只用于索引

1731379998193-c4a21cdb-f130-4a98-88cd-29ae91190f70.png

mysql 的 hash 索引结构

1731380189025-08f7344c-5b8d-422f-9c60-f02a75729da2.png

在 MySQL 中只有 Memory 引擎支持 hash 索引,但是

InnoDB 具有 hash 自适应功能,在指定条件下,会通过 B+树自动构建 hash 索引

面试题——为什么 InnoDB 选择 B+树索引结构

1731380439392-b5378721-6ede-48bb-b4e1-1497b9abcfdd.png

索引分类

1731380505764-42f9bec1-00e4-4315-9e1f-c03dbcf422e3.png

1731380652262-c2b702ce-7127-4eca-8699-3e8037b6b57f.png

二级索引又称为辅助索引、非聚集索引

聚集索引的自动选取规则:

  • 如果表中存在主键,那么主键索引就是聚集索引
  • 不存在主键,那么使用第一个唯一索引(unique)作为聚集索引
  • 没有主键和唯一索引,那么 InnoDB 会自动生成一个 rowid 作为隐藏的聚集索引

1731381114445-1df65cc8-b3b2-42fe-aa1d-2696646d26c3.png

聚集索引的叶子节点存储一行的数据

二级索引的叶子节点存储ID

那么查询的时候是如何工作的呢: 回表查询

如: select * from user where name = 'Lily'

首先在 name 字段对应的二级索引查询到名字对应的 ID 值,然后使用 ID 值在聚集索引中查询一行的数据并返回,称之为回表查询

思考:

select * from user where id = 10

select * from user where name = 'Lily'

以上两个查询哪个效率高:

答:第一个效率更高,直接查询 id 只需要在聚集索引中查找,不需要回表查询;而查询名字,需要先查找二级索引获得 id 再对聚集索引查询

1731381768281-fa08cd51-0bc7-47fe-84f2-13bc057770b8.png

索引操作语法

创建索引:

1731381874618-1480282d-4eab-491a-9b7e-9399d2abbf2d.png

创建常规索引不需要在 INDEX 前添加类型

一个索引可以关联多个字段

只关联一个字段的索引称为单列索引

关联多个字段的索引称为组合索引或联合索引

查看索引:

1731381977531-246c8ca2-8c22-4b93-b8d9-69b307eeadd5.png

删除索引:

1731382004131-f7c23dc6-3563-46c9-be10-3ed29cf83842.png

SQL 性能分析工具

语句执行次数查询

mysql 提供了以下命令来查看语句执行的次数

show global/session status like'Com_______'

global 为全局,session 为当前会话

通过此命令得知当前数据库占大多数的操作是什么,并针对此进行优化

1731416630625-68f6341c-9546-4d4b-8a3e-cc3b78adfcfb.png

慢查询日志

慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位秒,默认 10 秒)的所有 sql 语句操作

查询慢查询日志功能是否开启: show variables like'slow_query_log';

默认未开启

需要在 MySQL 的配置文件 /etc/my.cnf 中配置如下信息来打开慢查询日志功能

1731417022343-49cebe07-548c-493b-8dab-e3569717f253.png

慢查询日志文件 /var/lib/mysql/localhost-slow.log

通过查看该文件来查询执行效率低的 sql 操作

profile 详情

show profiles 能够在 sql 优化时,帮助我们了解某条 sql 语句的具体耗时,以及时间都耗在哪

select @@have_profiling 来查看当前数据库是否支持 profile 详情

select @@profiling 查看当前数据库是否开启 profile

默认关闭,

set profiling = 1 来打开 profile 详情

1731417917390-db591c8f-1f99-4204-ae0d-810045d2a1e0.png

查看指定 query_id 的 sql 操作在各个阶段的耗时情况:

show profile for query query_id

query_id 在 show profiles 中查看

1731475980255-2bb11260-a720-4a81-9392-a496c7f0acda.png

explain 执行计划

使用 explaindesc 可以获取 MySQL 如何执行 sql 语句的信息,如执行过程中表如何连接、连接顺序,索引等

1731476285815-4152fac4-5d3a-43dd-852d-f3e50c1ef077.png

1731477885535-3d81dc88-120a-4bc4-bbd5-4c93b7511788.png

1731477679169-110e095c-de4f-4a05-bc5f-a29d2b951ce0.png

1731477902147-87fd8124-8c63-44aa-a531-c21354ef51aa.png

优化目标:type 尽量往前,

system:系统表

const:主键或唯一约束的字段

ref:通常是不唯一字段

all:全表扫描,性能最低

索引使用原则

  1. 最左前缀法则

对于联合索引即关联了多个列的索引要遵循最左前缀法则

最左前缀法则:查询中,索引最左边的列必须存在,并且不跳过索引中的列

若跳跃了某一列,该列后的字段索引将会失效

指的是 where 之后的语句要遵循最左前缀法则,但是字段顺序无关,即只要存在最左列字段,且不跳过中间字段就行

  1. 对于范围查询右侧字段索引失效

对于范围查询来说,where 中的条件若出现了范围查询,范围查询后面的条件将不会使用索引来查询,而它前面的依然是索引

如联合索引的字段顺序为:profession、age、status

select * from tb_usr where profesion = '软件工程'and age = 30 and status = '0'

上述语句索引有效

select * from tb_usr where age = 30 and profesion = '软件工程'and status = '0'

上述语句只是交换了顺序,索引仍然有效

select * from tb_usr where profesion = '软件工程'and status = '0'

上述语句 where 条件中间的 age 没有,因此索引失效

select * from tb_usr where age = 30 and profesion = '软件工程'

上述语句索引有效,满足最左前缀法则。

那么对于以下查询

select * from tb_usr where profesion = '软件工程'and age > 30 and status = '0'

age>30 为范围查询,那么他后面 status='0' 的索引将失效,而它前面的 profession 依然生效

如果将**>**改为**>=**,那么索引就生效


  1. 运算会导致索引失效

如:字段 phone 已建立索引

select * from tb_user where substring(phone,10,2) = '15'

以上 sql 查询语句索引失效,type 为全表扫描

因此尽量不要在索引列上进行运算操作

  1. 字符串类型的索引列查询时不加单引号 ''索引失效

select * from tb_user where phone = 15829585395

以上查询失效,因为 phone 是字符串类型

上述语句可以正常查询出来

  1. 对于模糊查询 like,尾部不失效,头部失效

对尾部进行模糊匹配不失效,对头部进行模糊匹配则索引失效
select * from tb_user where phone like'158%'

上述索引不失效

select * from tb_user where phone like'%5395'

上述索引失效

  1. 对于 or 连接的条件,只有所有条件都有索引,索引才会生效

select * from tb_user where phone = '15829585395'or age =12

上述索引失效,由于联合索引的字段顺序为:profession、age、status,上述查询不遵循最左前缀法则

  1. 数据分布的影响

如果 MySQL 评估使用索引比全表扫描更慢,那么就不会使用索引

也就是对于索引列,若满足条件的行绝大多数,即返回的行占总的绝大多数,那么 MySQL 会认为全表扫描更快,反之返回行占少数,那么就会使用索引

  1. sql 提示

1731487339496-baf180bd-aa4f-4573-be2d-45bcafa1b8c6.png

use 是建议 MySQL

force 是强制

  1. 覆盖索引

尽量减少使用 select *,使用覆盖索引,即返回的字段被包含在使用的索引中

本质是避免回表查询,回表查询会降低效率

除非是使用 id 即主键,聚集索引查询, select * 也只需要一次查询,不需要回表查询

1731487836341-e759cfce-c08b-4735-8a1d-c4a1f18f3f77.png

上面的这个指的是 explain 中的 extra 字段

1731488460516-0d73a969-81e6-451d-a470-559b8f9a9552.png

思考:

1731488611221-544eab82-1d6e-4d84-8987-51da7bb07e9f.png

建立 usernamepassword 的联合索引,这样就不用回表查询

  1. 前缀索引

针对的问题:当字段类型为字符串(varchar,text 等),时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘 IO,影响查询效率。

此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

1731488798807-f705fbb2-8eb2-4fe0-8908-7175a854a757.png

前缀长度的选取:

1731488916188-3021373d-201d-4309-94b9-0c529e5e9b9b.png

尽量保证字符串长度更小和选择性更大的平衡

前缀索引的查询流程:

去前缀构建辅助索引后,查询时,在辅助索引时先搜索到 id,然后在聚集索引进行回表查询,找到对应 ID,对比查询条件是否成立,不成立则将辅助索引的叶子节点的下一个节点 ID 进行回表查询(B+树叶子节点是链表),知道匹配查询条件

1731490166841-f5458245-a155-44b7-b5cf-78742f1935b7.png

  1. 单列索引和联合索引的选择

在业务场景中,如果涉及多个查询条件,当要对查询字段建立索引时,建议建立联合索引

如: select id,phone,name from user_tb where phone = '123123312'and name = 'fdlajsk'

且 phone 和 name 各自有一个单列索引,那么 MySQL 只会选择评估效率比较高的一个索引来查询,然后进行回表查询匹配 name 的条件,并返回

而建立 phone 和 name 的联合索引,就不需要回表查询

联合索引的 B+树形式:

1731491247320-616dd07f-1466-4039-8b17-f91b86b5ae31.png

索引设计原则

  1. 针对数据量大(百万级别),且查询(索引用于提高检索效率)频繁的表建立索引
  2. 针对常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引
  3. 建索引时要对区分度高(独一无二,数据重复少)的字段建立索引

性别类似的字段只有男女,不如不建

  1. 对于字符串类型的字段,且通常长度非常长,建议建立前缀索引来提高检索效率
  2. 在多个字段条件的查询中,尽量使用联合索引,且联合索引很多时候可以覆盖索引,节省存储空间、避免回表查询,提高查询效率
  3. 只建立有必要的索引,要控制索引的数量,否则维护索引代价太大,影响增删改的效率
  4. 如果索引列不能存储 NULL 值,在建表时,应该使用 NOT NULL 进行约束。优化器知道每列是否包含 NULL 值时,才能更好的确定用哪个索引进行有效查询

其他 sql 语句优化

insert 优化

对于小规模数据插入的优化:

1731496618553-d791d5ea-3327-4a3d-ad34-ac1898c951fd.png

大规模数据的插入:load

1731496743369-224e6f67-b558-4ec1-a3a8-8767f69515db.png

1731496850451-e97a6d47-e2b7-42c1-99f0-f43eec16bb18.png

数据之间用’,'分隔,行用‘\n’分隔

视图/存储过程/触发器

视图(view)

视图:是一种虚拟存在的表,视图中的数据并不在数据库中真实存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成

通俗的讲,视图只保存了查询的 SQL 逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条 SQL 查询语句上

视图创建:

create [or replace] view 视图名 as select 语句 [with [cascaded | local] check option]

查询视图:

1731500956765-42fa6f32-d5f2-4e08-8bc5-50fb60490e43.png

修改视图:

1731501076713-cf9ca2ed-5809-4b7f-97a8-405977a69c0e.png

方式一和创建视图时的语句一样

区别在于:创建视图时,or replace 可以不加,但修改时必须加

删除视图:

1731501187777-8abd660d-bd12-405e-ab15-43da02e82ebd.png

创建视图时的检查选项_with [cascaded | local] check option_

在创建视图时加上检查选项后,对视图进行增删改时,MySQL 会对视图定义的条件进行检查,增删改的数据必须满足视图定义语句的条件

1731502353216-52056cbd-2156-4169-93af-33624b698676.png

local 和 cascaded 的区别:cascaded 会检查其上级视图的条件是否满足,即使上一级视图没有加视图检查选项,而 local 只关注当前视图的条件

只会向上级联!

视图是否可更新:

1731503275263-38e139c0-d4d6-4199-b4ac-3a32b584599c.png

可更新:可以进行增删改

视图的作用:

由于数据库的授权最多到表,不能控制行和字段,因此若只想表中某几个字段对用户可见,就可以创建一个视图,其中只包含这几个字段,表中的另外字段用户就不可见了

1731503565973-390bc28b-ff45-4e15-8357-c8e124219bae.png

存储过程

存储过程:事先经过编译并存储在数据库中的 sql 语句集合

调用存储过程可以简化开发人员的工作,减少数据在数据库和应用服务器之间传输的次数,以提高数据处理效率

存储过程的思想就是 sql 语句的代码封装和重用

存储过程的特点:

  • 封装和复用
  • 可以接收参数,也可以返回数据
  • 减少网络交互,减少网络 IO 的交互频率,提升效率

存储过程的创建:

1731504283402-62f7a5f3-fc10-4f40-b7b5-5aeb7be8c69d.png

如:

1731504400786-4e06c9fb-d67b-44af-b472-54851a3450e3.png

在命令行中创建存储过程时,默认分号为结束符,那么就会出问题

delimiter 符号 可以指定结束符
delimiter $$ 那么 MySQL 将会默认 $$ 代替分号作为结束符

调用:

call 存储过程名(参数)

call p1()

查看存储过程:
1731504453209-c58f8b4a-1ad4-4a43-b11e-1473395ca19d.png

删除:

1731504710584-177652e0-5164-4a2f-b047-ae20e2a94110.png

InnoDB 引擎

逻辑存储结构

表-段-区-页-行

1731505368814-d0a7eaec-6519-43de-a2c1-162d1184f6ac.png

1731505553488-eebb0c4d-84da-45d4-95ed-bf5f4112034d.png

每个表都有一个对应的 ibd 文件

1731505576816-019f2203-825f-4530-b7e2-087efb68effa.png

1731505605551-20c90ad7-6d71-4e2f-8ede-7f7f4a387d79.png

1731505613653-53f9d566-af67-42c4-aaee-d88e34c0b5fa.png

1731505633374-55548c7c-e352-4f6b-b8e7-d34525b0acf2.png

架构

1731505752981-e2be7bd6-e1ca-4923-89be-2758321a0f87.png

内存结构:

1731505930581-97dcf6f7-fbc5-4c75-a5ab-9733183d6ff5.png

1731505937850-95c9c6d0-0cc7-40d5-b48e-2848aed778aa.png

1731506012795-9534173b-66d8-43fc-9a47-d9030363c958.png

1731506094407-f703f630-861a-4077-9ee7-01d5e788547a.png

1731506192610-996a09f5-e2b6-4c55-ba8d-ae852de1671b.png

1731506345442-b8911978-c1ad-4ed6-beaa-221f2694882a.png

磁盘结构:

1731506461523-8d109f9a-2f7e-4305-8eb7-a8e22c8dfa24.png

1731506498929-f46635df-b5fc-4d40-b9a6-588cb3a8536c.png

1731506655606-309fba7e-944b-4542-8dbc-7cade8d301ab.png

1731506753702-73dc300e-1b65-4d46-9f33-aaf1319a0cce.png

1731506767039-05e3cfab-5bab-43f8-9127-8b03ca7afb37.png

1731506825070-f977ebdc-7f11-48b5-acc3-20cec614d6cf.png

1731506904676-e6a46507-0ef8-4d47-8c98-7274e668a69a.png

后台线程: