自己学习MySQL时整理的笔记,包括实操中遇到的问题,不同版本之间的差异。后续也会继续完善,有PDF文档版。
学习视频:https://www.bilibili.com/video/BV1Kr4y1i7ru?t=1.9
怎么学,收获?
基础篇:(初级工程师)
- MySQL概述
- SQL
- 函数
- 约束
- 多表查询
- 事务
进阶篇:(中级工程师)
- 存储引擎
- 索引
- SQL优化
- 视图/存储过程/触发器
- 锁
- InnoDB核心
- MySQL管理
运维篇:(高级工程师)
MySQL初级篇
MySQL概述
- 数据库(DB)
- 数据库管理系统(DBMS)
- SQL
- 操作关系型数据库的编程语言,定义了操作关系型数据库的统一标准
关系型数据库(RDBMS)
建立在关系模型基础上,由多张相互连接的二维表组成的数据库。
特点:
- 使用表存储数据,格式统一,便于维护
- 使用SQL语言操作,标准统一,使用方便
MySQL数据库 数据模型
客户端–连接–DBMS–使用sql语句通过DBMS创建数据库/表/存储数据
SQL
- sql通用语法
- sql分类
- DDL
- DML
- DQL
- DCL
SQL通用语法
- SQL语句可以单行或多行书写,以分号结尾
- SQL语句可以使用空格/缩进来增强可读性
-
MySQL数据库的SQL语句不区分大小写,关键字建议使用大写
- 注释:
- 单行注释:
--
注释内容 或 #
注释内容(MySQL特有)
- 多行注释:
/*注释内容*/
SQL分类
分类 |
说明 |
DDL |
数据库定义语言,用来定义数据库对象(数据库,表,字段) |
DML |
数据库操作语言,用来对数据库表中的数据进行增删改 |
DQL |
数据库查询语言,用来查询数据库中表的记录 |
DCL |
数据库控制语言,用来创建数据库用户、控制数据库的访问权限 |
DDL
DDL-数据库操作
查询、创建、删除、使用
# 查询
show databases; -- 查询所有数据库
select database(); -- 查询当前数据库
# 创建
create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则];
# 删除
drop databse [if exists] 数据库名;
# 使用
use 数据库名;
DDL-表操作
查询、创建、修改、删除
查询
# 查询
show tables; -- 查询当前数据库所有表
desc 表名; -- 查询表结构
show create table 表名; -- 查询指定表的建表语句
创建
create table 表名(
字段1 字段1类型 [comment 字段1注释],
字段2 字段2类型 [comment 字段2注释],
字段3 字段3类型 [comment 字段3注释],
......
字段n 字段n类型 [comment 字段n注释]
)[comment 表注释];
注意:[…]为可选参数,最后一个字段后没有逗号
DDL-表操作-数据类型
MySQL中的数据类型有很多,主要分为三类:数值、字符串、日期时间
数值类型
字符串类型
二进制数据(视频/音频/安装包)开发当中一般不怎么做,性能不高,一般采用专门的文件服务器存储
定长字符串char(10) 和 变长字符串varchar(10)
相同点:10代表最多只能存储10个字符,一旦超过就报错
不同:
- char(10)—>性能好:即使存储一个字符,也会占用10个字符空间,其它空间用空格补位
- varchar(10)—>性能较差:存储一个字符就占用一个字符空间,根据存储内容去计算占用的空间是多少
日期时间类型
修改
添加字段
alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];
alter table test add email varchar(20) comment '邮件';
desc test; -- 查看表信息,进行验证
修改数据类型
alter table 表名 modify 字段名 新数据类型(长度);
修改字段名和字段类型
alter table 表名 change 旧字段名 新字段名 类型(长度) [comment 注释][约束];
删除字段
alter table 表名 drop 字段名;
修改表名
alter table 表名 rename to 新表名;
删除
删除表
drop table [if exists] 表名;
删除指定表,并重新创建该表
truncate table 表名; -- 原表的结构并不会变
DML
数据操作语言:对数据中表的数据进行增、删、改
- 添加数据:insert
- 修改数据:update
- 删除数据:delete
DML-添加数据
-
给指定字段添加数据
insert into 表名(字段1,字段2,...)values(值1,值2);
-
给全部字段添加数据
insert into 表名 values(值1,值2,...);
-
批量添加数据
insert into 表名(字段1,字段2,...) values(值1,值2,...),(值1,值2,...),(值1,值2,...);
insert into 表名 values(值1,值2,...),(值1,值2,...),(值1,值2,...);
注意:
- 插入数据时,指定的字段顺序需要与值的顺序是一一对应的
- 字符串和日期型数据应该包含在引号中
- 插入的数据大小,应该在字段的规定范围内
DML-修改数据
update 表名 set 字段1=值1, 字段2=值2, ... [where 条件];
注意:修改语句的条件可以有,也可以没有,没有条件则会修改整张表的所有数据
DML-删除数据
delete from 表名 [where 条件];
注意:
- delete语句的条件可以有,也可以没有,没条件则表示删除整张表的所有数据
- delete语句不能删除某一个字段的值(可以使用update)
DQL
数据库查询语言,查询数据库中表的记录
关键字:select
DQL-语法
-- 编写顺序
select
字段列表
from
表名列表
where
条件列表
group by
分组字段列表
having
分组后条件列表
order by
排序字段列表
limit
分页参数
- 基本查询
- 条件查询(where)
- 聚合函数(count、max、min、avg、sum)
- 分组查询(order by)
- 分页查询(limit)
DQL-基本查询
-
查询多个字段
select 字段1,字段2,字段3... from 表名;
select * from 表名;
-
设置别名
select 字段1[as 别名1], 字段2[as 别名2] ... from 表名; # as可以省略不写
-
去除重复记录
select distinct 字段列表 from 表名;
DQL-条件查询
-
语法
select 字段列表 from 表名 where 条件列表;
-
条件
比较运算符 |
功能 |
逻辑运算符 |
功能 |
> |
大于 |
and 或 && |
并且(多个条件同时成立) |
>= |
大于等于 |
or 或 || |
或者(多个条件任意一个成立) |
< |
小于 |
not 或 ! |
非,不是 |
<= |
小于等于 |
|
|
= |
等于 |
|
|
<> 或 != |
不等于 |
|
|
between…and … |
在某个范围之内(含最小、最大值) |
|
|
in(…) |
在in之后的列表中的值,多选一 |
|
|
like 占位符 |
模糊匹配(_匹配单个字符,%匹配任意个字符) |
|
|
is NULL |
为空 |
|
|
DQL-聚合函数
通常进行分组查询的时候,会配合着聚合函数来操作
-
介绍
将一列数据作为一个整体,进行纵向计算。
-
常见的聚合函数
函数 |
功能 |
count |
统计数量 |
max |
最大值 |
min |
最小值 |
avg |
平均值 |
sum |
求和 |
-
语法
select 聚合函数(字段列表) from 表名;
select avg(age) from user;
注意:NULL值不参与聚合函数运算。
DQL-分组查询
-
语法
select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];
-
where与having区别
- 执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤。
- 判断条件不同:where不能对聚合函数进行判断,而having可以。
-
注意
DQL-排序查询
-
语法
select 字段列表 from 表名 order by 字段1 排序方式1, 字段2 排序方式2;
-
排序方式
-
注意:如果是多字段排序,当第一个字段值相同时,才会根据第二字段进行排序。
DQL-分页查询
-
语法
select 字段列表 from 表名 limit 起始索引, 查询记录数;
-
注意
- 起始索引从0开始,起始索引 =(查询页码 -1)* 每页显示记录数。
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中的是limit。
- 如果查询的是第一页数据,起始索引可以省略,直接简写为limit 10。
DQL-执行顺序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOD84083-1687944484121)(D:\0-视频#-笔记\MySQL\笔记配图\DQL-执行顺序.png)]
DCL
数据库控制语言,用来管理数据库用户、控制数据库的访问权限。
DCL-管理用户
-
查询用户
use mysql;
select * from user;
-
创建用户
create user '用户名'@'主机名' identified by '密码';
主机名:localhost 只能本机访问,改为 % 表示任意主机访问
用户名和主机地址才能定位一个MySQL用户
-
修改用户密码
set password for '用户名'@'主机名' = password('新密码');
# 新密码必须使用 PASSWORD() 函数来加密,若不使用 PASSWORD() 加密,也会执行成功,但是用户会无法登录。
alter user '用户名'@'主机名' identified by '新密码'; # 好像只有5.7以上的版本支持alter修改
alter user '用户名'@'主机名' identified with mysql_native_password by '新密码'; # 修改身份验证插件
注意版本:
- mysql5.7版本之前,修改用户密码使用set、update
- mysql5.7版本之后,password属性已经取消(使用SELECT Password(‘123’) 会报错),修改用户密码的语句已经改变
- 在MySQL 5.7中,默认的身份验证插件还是为
mysql_native_password
。
- 在MySQL 8.0中,
caching_sha2_password
是默认的身份验证插件,此方式并不兼容常规的老的web服务接口。
- 像在使用MySQL的可视化工具Navicat时,又或者Django和MySQL的配合使用,由于Django不支持新版本MySQL的加密方式,会报错,所以需要将默认的连接方式恢复为旧的
mysql_native_password
方式。
-
删除用户
drop user '用户名'@'主机名';
注意:
- 主机名可以使用通配符 %
- 这类SQL开发人员操作的比较少,主要是DBA(Database Administrator 数据库管理员)使用。
DCL-权限控制
注意:MySQL中 test 数据库比较特别,所有能连接到MySQL的用户,几乎都拥有test库的所有权限。
详情:mysql的test 库的相关特性-renwd-ChinaUnix博客
MySQL中定义了很多种权限,但是常用的就以下几种:
权限 |
说明 |
all, all privileges |
所有权限 |
select |
查询数据 |
insert |
插入数据 |
update |
修改数据 |
delete |
删除数据 |
alter |
修改表 |
drop |
删除数据库/表/视图 |
create |
创建数据库/表 |
-
查询权限
show grants for '用户名'@'主机名';
-
授予权限
grant 授权列表 on 数据库名.表名 to '用户名'@'主机名';
-
撤销权限
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
注意:
- 多个权限之间,使用逗号分隔
- 授权时,数据库名和表名可以使用 * 进行通配,代表所有。
函数
函数是一段可以直接被另一段程序调用的程序或代码。
字符串函数
MySQL中内置了很多字符串函数,常用的几个如下:
函数 |
功能 |
concat(S1, S2, …Sn) |
字符串拼接,将S1, S2, …Sn拼接成一个字符串 |
lower(str) |
将字符串 str 全部转为小写 |
upper(str) |
将字符串 str 全部转为大写 |
lpad(str, n, pad) |
左填充,用字符串 pad 对 str 的左边进行填充,达到n个字符串长度 |
rpad(str, n, pad) |
又填充,用字符串 pad 对 str 的右边进行填充,达到n个字符串长度 |
trim(str) |
去掉字符串头部和尾部的空格 |
substring(str, start, len) |
返回从字符串 str 从 start 位置起的 len 个长度的字符串 |
数值函数
常见的数值函数如下:
函数 |
功能 |
cell(x) |
向上取整 |
floor(x) |
向下取整 |
mod(x,y) |
返回x/y的模 |
rand() |
返回0-1内随机数 |
round(x,y) |
求参数x的四舍五入的值,保留y位小数 |
日期函数
常见日期函数如下:
函数 |
功能 |
curdate() |
返回当前日期 |
curtime() |
返回当前时间 |
now() |
返回当前日期和时间 |
year(date) |
获取指定date的年份 |
month(date) |
获取指定date的月份 |
day(date) |
获取指定date的日期 |
date_add(date, interval expr type) |
返回一个日期/时间值加上一个时间间隔expr后的时间值 |
datediff(date1, date2) |
返回起始时间date1和结束时间date2之间的天数 |
流程函数
流程函数也是常用的一类函数,可以在SQL语句中实现条件筛选,从而提高语句的效率。
函数 |
功能 |
if(value, t, f) |
如果value为true,则返回t,否则返回f |
ifnull(value1, value2) |
如果value不为空,返回value1,否则返回value2 |
case when [val1] then [res1] … else [default] end |
如果val1为true,返回res1,…否则返回default默认值 |
case [expr] when [val1] then [res1] … else [default] end |
如果表达式expr的值等于val1,返回res1,…否则返回default默认值 |
约束
概述
-
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。
-
目的:保证数据库中数据的正确、有效性和完整性、
-
分类
约束 |
描述 |
关键字 |
非空约束 |
限制该字段的数据不能为null |
not null |
唯一约束 |
保证该字段的所有数据都是唯一、不重复的 |
unique |
主键约束 |
主键是一行数据的唯一标识,要求非空且唯一 |
primary key |
默认约束 |
保存数据时,如果未指定该字段的值,则采用默认值 |
default |
检查约束(8.0.16版本之后) |
保证字段值满足某一个条件 |
check |
外键约束 |
用来让两张表的数据之间建立连接,保证数据的一致性和完整性 |
foreign key |
注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
约束演示
案例:根据需求,完成表结构的创建
字段名 |
字段含义 |
字段类型 |
约束条件 |
约束关键字 |
id |
ID唯一标识 |
int |
主键,并且自动增长 |
primary key, auto_increment |
name |
姓名 |
varchar(10) |
不为空,并且唯一 |
not null, unique |
age |
年龄 |
int |
大于0,并且小于等于120 |
check |
status |
状态 |
char(1) |
如果没有指定该值,默认为1 |
default |
gender |
性别 |
char(1) |
无 |
|
-- 约束演示
create table user(
id int primary key auto_increment comment '主键',
name varchar(10) not null unique comment '姓名',
-- 8.0.16版本之前不支持检查约束 age int check (age > 0 and age <= 120) comment '年龄',
age tinyint unsigned comment '年龄',
status char(1) default '1' comment '状态',
gender char(1) comment '性别'
) comment '用户表';
外键约束
概念
外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性
-- -----------------------------约束(外键)------------------------
-- 准备数据
create table dept( -- dept:部;科(department)
id int auto_increment comment 'ID' primary key,
name varchar(10) not null comment '部门名称'
) comment '部门表';
insert into dept(id,name) values (1,'研发部'),(2,'市场部'),(3,'财务部'),(4,'销售部'),(5,'总经办');
create table emp(
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '姓名',
age tinyint unsigned comment '年龄',
job varchar(20) comment '职位',
salary int comment '薪资',
entrydate date comment '入职日期',
managerid int comment '直属领导ID',
dept_id int comment '部门ID'
)comment '员工表';
insert into emp (id,name,age,job,salary,entrydate,managerid,dept_id) values
(1,'金庸',66,'总裁',20000,'2000-01-01',null,5),
(2,'张无忌',20,'项目经理',12500,'2005-12-05',1,1),
(3,'杨逍',33,'开发',8400,'2000-11-03',2,1),
(4,'韦一笑',48,'开发',11000,'2002-02-05',2,1),
(5,'常遇春',43,'开发',10500,'2004-09-07',3,1),
(6,'小昭',19,'程序员鼓励师',6600,'2004-10-12',2,1);
语法
-
添加外键
-- 建表时添加
create table 表名(
字段名 数据类型,
...
[constraint] [外键名称] foreign key(外键字段名) references 主表(主表列名)
);
-- constraint:n. 限制,束缚;克制,拘束
-- foreign:adj. 外国的;外交的,涉外的;陌生的,不熟悉的;外来的,异质的;外地的,不属于本地区的
-- references:n. [图情]参考文献;参照;推荐信 v. 附……以供参考;把……引作参考
-- 表创建好后 额外增加外键
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名);
-
删除外键
alter table 表名 drop foreign key 外键名称;
-
删除/更新行为
行为 |
说明 |
no action |
当在父表中删除/更新对于记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与 restrict 一致) |
restrict |
当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与 no action 一致) |
cascade |
当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。 |
set null |
当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(这就要求该外键运行取null)。 |
set default |
父表有变更时,子表将外键列设置成一个默认值(Innodb不支持) |
alter table 表名 add constraint 外键名称 foreign key (外键字段) references 主表名(主表字段名) on update cascade on delete cascade;
外键设置不成功:原因有很多【比如引擎不对等】
多表查询
- 多表关系
- 多表查询概述
- 内连接
- 外连接
- 自连接
- 子查询
- 多表查询案例
多表关系
概述:项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表之间也存在各种联系,基本上分为三种:
一对多(多对一)
-
案例:部门 与 员工的关系
-
关系:一个部门对应多个员工,一个员工对应一个部门
-
实现:在多的一方建立外键,指向一的一方的主键
多对多
一对一
多表查询概述
内连接
内连接查询的是两张表交集的部分
内连接查询语法:
条件不匹配的不会被查询出来
外连接
外连接语法:
自连接
案例:查询员工 及其 所属领导的名字
自连接查询语法:
select 字段列表 from 表A 别名A join 表A 表名B on 条件 ...;
select 字段列表 from 表A 别名A,表A 表名B where 条件...;
自连接必须起别名。
自连接查询,可以是内连接查询,也可以是外连接查询。
联合查询-union,union all
对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
select 字段列表 from 表A ...
union [all]
select 字段列表 from 表B ...;
- 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致
- union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。
子查询
-
概念:SQL语句中嵌套select语句,称为嵌套查询,又称子查询。
select * from t1 where column1 = (select column1 from t2);
子查询外部的语句可以是 insert / update / delete / select 的任何一个。
-
根据子查询结果不同,分为:
- 标量子查询(子查询结果为单个值)
- 列子查询(子查询结果为一列)
- 行子查询(子查询结果为一行)
- 表子查询(子查询结果为多行多列)
-
根据子查询位置,分为:where之后、from之后、select之后。
标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。
列子查询
子查询返回的结果是一列(可以是多行),这种子查询称为列子查询
行子查询
子查询返回的结果是一行(可以是多列),这种子查询称为行子查询
表子查询
子查询返回的结果是多行多列,这种子查询称为表子查询。
多表查询练习
48. 基础-多表查询-练习1_哔哩哔哩_bilibili
多表查询写法不固定,很多场景下可以通过子查询来实现,也可以通过多表联查来实现
事务
- 事务简介
- 事务操作
- 事务四大特性
- 并发事务问题
- 事务隔离级别
事务简介
事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作 要么同时成功,要么同时失败。
默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。
事务操作
注意:MyISAM存储引擎是不支持事务处理的。
事务控制可以两种方式:
- 将事务改为手动提交,通过
commit
提交事务 或 rollback
回滚事务。
- 通过
start transaction 或 begin
显式的来开启事务,事务执行操作完成之后,如果事务执行成功 执行commit
,如果失败执行rollback
指令。
事务的四大特性
- 原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性:事务完成时,必须使所有的数据都保持一致状态。
- 隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
- 持久性:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
并发事务问题
多个并发事务在执行的过程当中,所出现的脏读、不可重复读、幻读的问题。
问题 |
描述 |
脏读 |
一个事物读到另一个事务还没提交的数据。
|
不可重复读 |
一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
|
|
|
幻读 |
一个事物按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现了这行数据已经存在,好像出现了“幻影”。
|
|
|
不可重复读两次查询结果不同,前提事务B提交了,没提交那叫脏读。
事务的隔离级别
用来解决并发事务所引发的问题的。
注意:事务隔离级别越高,数据越安全,但是性能越低。
隔离级别 |
脏读 |
不可重复读 |
幻读 |
read uncommitted |
√ |
√ |
√ |
read committed |
× |
√ |
√ |
repeatable read(默认) |
× |
× |
√ |
serializable |
× |
× |
× |
√:表示会出现这种问题
×:表示已解决这种问题
repeatable read(MySQL的默认事务隔离级别)
-
查看事务隔离级别
-- MySQL8.0+
select @@transaction_isolation; -- 查看当前会话隔离级别
select @@global.transaction_isolation; -- 查看系统当前隔离级别
-- MySQL5.0+
select @@tx_isolation; -- 查看当前会话隔离级别
select @@global.tx_isolation; -- 查看系统当前隔离级别
-
设置事务隔离级别
set [session|global] transaction isolation level {read uncommitted | read committed | repeatable read | serializable}
总结
-
事务简介
事务是一组操作的集合,这组操作,要么全部执行成功,要么全部执行失败。
-
事务操作
start transaction; -- 开启事务
commit / rollback; -- 提交/回滚事务
-
事务四大特性(ACID)
原子性(Atomicity)、一致性(Consistency)、隔离性 (Isolation)、持久性(Durability)
-
并发事务问题
脏读、不可重复读、幻读
-
事务隔离级别
read uncommitted | read committed | repeatable read | serializable
MySQL进阶篇
- 存储引擎
- 索引
- SQL优化
- 视图/存储过程/触发器
- 锁
- InnoDB引擎
- MySQL管理
存储引擎
- MySQL体系结构
- 存储引擎简介
- 存储引擎特点
- 存储引擎选择
MySQL体系结构
MySQL5.5之后版本默认存储引擎为 InnoDB
-
连接层
最上层是一些客户端和链接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。
-
服务层
第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如:过程、函数等。
-
引擎层
存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需求,来选择合适的存储引擎。
-
存储层
主要是将数据存储在文件系统之上,并完成与存储引擎的交互。
存储引擎简介
存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被称为表类型。
-
在创建表时,指定存储引擎
create table 表名(
字段1 字段1类型 [comment 字段1注释],
...
字段n 字段n类型 [comment 字段n注释]
)engine = innodb [comment 表注释];
-
查看当前数据库支持的存储引擎
show engines;
存储引擎特点
InnoDB
-
介绍:
InnoDB是一种兼顾高可靠性和高性能的通用存储引擎,在MySQL 5.5之后,InnoDB是默认的存储引擎。
-
特点
DML操作遵循ACID模型,支持 事务;
行级锁,提高并发访问性能;
支持 外键 foreign key 约束,保证数据的完整性和正确性;
-
文件
xxx.ibd:xxx代表的是表名,innoDB引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引。
早期表结构都存储在frm
文件中,MySQL 8.0之后表结构都存储在sdi
这个数据字典当中,sdi有融入了idb表空间文件当中。
参数:innodb_file_per_table【该参数决定是多张表共用一个共享空间,还是说每一张表都对应一个表空间文件】
-
Innodb的逻辑存储结构
MyISAM
Memory
三种存储引擎的区别
特点 |
InnoDB |
MyISAM |
Memory |
存储限制 |
64TB |
有 |
有 |
事务安全 |
支持 |
- |
- |
锁机制 |
行锁 |
表锁 |
表锁 |
B+tree索引 |
支持 |
支持 |
支持 |
Hash索引 |
- |
- |
支持 |
全文索引 |
支持(5.6版本之后) |
支持 |
- |
空间使用 |
高 |
低 |
N/A |
内存使用 |
高 |
低 |
中等 |
批量插入速度 |
低 |
高 |
高 |
支持外键 |
支持 |
- |
- |
存储引擎选择
在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组合。
- InnoDB:支持事务、外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作,那么InnoDB存储引擎是比较合适的选择。
- MyISAM:如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常合适的。
- Memory:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。Memory的缺陷就是对表的大小有限制,太大的表无法在内存中,而且无法保障数据的安全性。
总结
-
体系结构
连接层、服务层、引擎层、存储层
-
存储引擎简介
show engines; -- 查看当前数据库支持的存储引擎
create table xxx(...)engine=innodb; -- 建表时指定存储引擎
-
存储引擎特点
Innodb 与 MyISAM:事务、外键、行级锁
-
存储引擎应用
INNODB:存储业务系统中对于事务、数据完整性要求较高的核心数据。
MYISAM:存储业务系统的非核心事务。
索引
- 索引概述
- 索引结构
- 索引分类
- 索引语法
- SQL性能分析
- 索引使用
- 索引设计原理
索引概述
索引结构
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含一下几种:
索引结构 |
描述 |
B+Tree索引 |
最常见的索引类型,大部分引擎都支持 B+树 索引 |
Hash索引 |
底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询 |
R-tree(空间索引) |
空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
Full-text(全文索引) |
是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES |
不同存储引擎,索引结构的支持情况:
索引 |
InnoDB |
MyISAM |
Memory |
B+tree 索引 |
支持 |
支持 |
支持 |
Hash 索引 |
不支持 |
不支持 |
支持 |
R-tree 索引 |
不支持 |
支持 |
不支持 |
Full-text |
5.6版本之后支持 |
支持 |
不支持 |
我们平常所说的索引,如果没有特别指明,都是指 B+树结构组织的索引。
索引结构-Btree
11. 进阶-索引-结构-Btree_哔哩哔哩_bilibili
索引结构-B+tree
以一一颗最大度数为4的 b+tree 为例:
相对于B-tree区别:
- 所有的数据都会出现在叶子节点
- 叶子节点形成一个单向链表
MySQL索引数据结构对经典的B+tree进行了优化。在原B+tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+tree,提高区间访问的性能。
索引结构-Hash
哈希索引就是采用一定的hash算法,将.键值换算成新的hash值,映射到对应的槽位上,然后再存储在hash表中。
如果两(或多个)键值,映射到一个相同的槽位上,他们就产生了冲突(也称hash碰撞),可以通过链表来解决。
Hash索引特点:
- hash索引只能用于对等比较(=,in),不支持范围查询(between,<,>,…)
- 无法利用索引完成排序操作
- 查询效率高,通常只需要一次检索就可以了,效率通常要高于B+tree索引
存储引擎支持:
- 在MySQL,支持hash索引的是Memory引擎,而InnoDB中具有自适应hash功能,hash索引是存储引擎根据B+tree索引在指定条件下自动构建的。
索引结构-思考
为什么InnoDB存储引擎选择使用B+tree索引结构?
- 相对于二叉树,层级更少,搜索效率更高;
- 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要保存同样大量数据,只能增加树的高度,导致性能降低;对于B+tree,不管查找哪个数据,都要到叶子节点中找,搜索效率稳定,而且叶子节点形成一个双向链表,便于范围搜索和排序;
- 相对于Hash索引,B+tree支持范围匹配及排序操作;
索引分类
分类 |
含义 |
特点 |
关键字 |
主键索引 |
针对于表中主键创建的索引 |
默认自动创建,只能有一个 |
primary |
唯一索引 |
避免同一个表中某数据列中的值重复 |
可以有多个 |
unique |
常规索引 |
快速定位特点数据 |
可以有多个 |
|
全文索引 |
全文索引查找的是文本中的关键词,而不是比较索引中的值 |
可以有多个 |
fulltext |
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:
分类 |
含义 |
特点 |
聚集索引 |
将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据 |
必须有,而且只有一个 |
二级索引 |
将数据与索引分开存储,索引结构的叶子节点关联的是对于的主键 |
可以存在多个 |
聚集索引选取规则:
- 如果存在主键,主键索引就是聚集索引。
- 如果不存在主键,将使用第一个唯一索引作为聚集索引。
- 如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。
思考
-
一下SQL语句,哪个执行效率高,为什么?
select * from user where id=10;
select * from user where name='Aem';
-- id为主键,name字段创建的有索引
id查询效率高;根据id只需要到聚集索引中对比,根据name查,首先要到name字段对应的二级索引来查,查找到对应的id,再根据id到聚集索引中去查询整行数据。
-
InnoDB主键索引的B+tree高度为多少?
索引语法
-
创建索引
create [unique | fulltext] index index_name on table_name(index_col_name,...);
-
查看索引
show index from table_name;
注意:什么索引类型;哪个字段;什么数据结构
-
删除索引
drop index index_name on table_name
案例展示:https://www.bilibili.com/video/BV1Kr4y1i7ru?t=213.0&p=74
SQL性能分析
SQL执行频率
MySQL客户端连接成功之后,通过show [session|global] status
命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的 insert、update、delete、select的访问频次:
show global status like 'com_______'; # 7个下划线 代表7个字符
慢查询日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。
MySQL的慢查询日志默认没有开启,需要在MySQL配置文件(/etc/my.cnf)中配置如下信息:
# 开启MySQL慢查询日志查询开关
show_query_log=1
# 设置慢查询日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志
long_query_time=2
配置完毕之后,通过以下指令重启MySQL服务进行测试,查看慢查询日志文件中的记录信息 /var/lib/mysql/localhost-show.log
profile详情
show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里了。通过have_profiling参数,能够看到当前MySQL是否支持profile操作:
select @@have_profiling;
默认profiling是关闭的,可以通过set语句在session/global级别开启profiling:
set profiling=1;
执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:
-- 查看每一条SQL的耗时基本情况
show profiles;
-- 查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
-- 查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;
explain执行计划
explain 或者 desc命令获取MySQL如何执行select语句的信息,包括在select语句执行过程中表如何连接和连接的顺序。
语法:
-- 直接在select语句之前加上关键字explain/desc
explain select 字段列表 from 表名 where 条件;
explain执行计划各字段含义:
-
id
select 查询的序列号,表示查询中执行select子句或者是操作表的顺序(id相同,执行顺序从上至下;id不同,值越大,越先执行)
多表查询有多条记录,多个id
-
select_type
表示select的类型,常见的取值有simple(简单表,即不使用表连接或者子查询)、primary(主查询,即外层的查询)、union(union中的第二个或者后面的查询语句)、subquery(select/where之后包含了子查询)等
-
type
表示连接类型,性能由好到差的连接类型为null、system、const、eq_ref、ref、range、index、all。
不访问任何表为null;system:访问系统表;const:根据主键,唯一索引访问;ref:根据非唯一性索引访问
-
possible_key
显示可能应用在这张表上的索引,一个或多个。
-
key
实际使用的索引,如果为null,则没有使用索引
-
key_len
表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精度的前提下,长度越短越好。
-
rows
MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估量值,可能并不准确。
-
filtered
表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。
索引使用
验证索引效率
22. 进阶-索引-使用规则-验证索引效率_哔哩哔哩_bilibili
最左前缀法则
如果索引了多列(联合索引),要遵守最左前缀法则。 最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将部分失效(后面的字段索引失效)。
23. 进阶-索引-使用规则-最左前缀法则_哔哩哔哩_bilibili
索引失效情况
SQL提示
SQL提示,是优化数据库的一个主要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
-
use index 告诉数据库使用哪个索引
explain select * from tb_user use index(id_user_pro) where profession='软件工程';
只是建议MySQL使用指定的索引,具体还得看这个索引快不快,MySQL接不接受
-
ignore index 告诉数据库忽略哪个索引
explain select * from tb_user ignore index(id_user_pro) where profession='软件工程';
-
force index 强制数据库必须使用哪个索引
explain select * from tb_user force index(id_user_pro) where profession='软件工程';
覆盖索引
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select *
。
27. 进阶-索引-使用规则-覆盖索引&回表查询_哔哩哔哩_bilibili
using index condition:查找使用了索引,但是需要回表查询数据
using where;using index:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据
思考:
-
一张表,有四个字段(id、username、password、status),由于数据量大,需要对以下SQL语句进行优化,该如何进行才是最佳方案:
select id,username,password from tb_user where username='Tom';
-- 针对username、password这两个字段建立联合索引【联合索引就是二级索引,叶子节点下挂的就是id】
-- 这个时候再执行这条语句时直接覆盖索引不用回标查询
前缀索引
当字段类型为字符串(varchar、text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
-
语法
create index idx_xxx on table_name(column(n)); -- n表示提取这个字符串的前面n个字符建立索引
-
前缀长度
可以根据索引字段的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也最好。
-- 计算选择性公式:不重复数/数据表记录总数
select count(distinct email)/count(*) from tb_user; -- distinct 去重
select count(distinct substring(email,1,5))/count(*) from tb_user; -- substring 截取字符串
-
前缀索引查询流程
28. 进阶-索引-使用规则-前缀索引_哔哩哔哩_bilibili
单列索引与联合索引
单列索引:即一个索引只包含单个列。
联合索引:即一个索引包含了多个列。
在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。
索引设计原则
-
针对于数据量较大,且查询比较频繁的表建立索引。
上百万数据,几千条不用索引效率也高
-
针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
-
尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度高,使用索引的效率越高。
-
如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
-
尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
最左前缀法则
-
要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价就越大,会影响增删改的效率。
-
如果索引列不能存储NULL值,请在创建表时用not null约束它。当优化器知道每列是否包含null值时,它可以更好的确定哪个索引最有效地用于查询。
索引总结
-
索引概述
索引是高效获取数据的数据结构;
-
索引结构
B+tree
所有数据都会出现在叶子节点,叶子节点形成一个双向链表。
Hash
Memory存储引擎支持,一个哈希表,检索性能很高,只需计算出字段值的哈希值,然后定位到对应数据,如果存在对应的哈希碰撞,需要沿着链表再找到对应数据。缺点:只支持精确匹配,不支持范围查询,以及索引的排序。
-
索引分类
两个层面的分类
第一个:主键索引、唯一索引、常规索引、全文索引
第二个:innodb存储引擎中,根据索引的存储结构分为:聚集索引、二级索引
聚集索引B+tree叶子节点挂的是这一行的数据,而二级索引叶子节点挂的是对应的主键
-
聚集索引
innodb存储引擎的表当中必须存在,而且只有一个
默认主键就是聚集索引,如果没有主键,选择第一个唯一索引作为聚集索引;如果既没有主键,又没有唯一索引,MySQL会自动生成一个隐藏的rowID作为聚集索引。
-
二级索引
-
索引语法
-- 如何创建索引、删除索引、查看索引
create [unique] index xxx on xxx(xxx);
show index from xxx;
drop index xxx on xxx;
-
SQL性能分析
执行频次、慢查询日志、、profile、explain
-
索引使用
联合索引
使用联合索引时,遵循最左前缀法则
索引失效
- 在索引列上进行函数运算,索引失效
- 字符串不加引号,造成隐式类型转换,索引失效
- like模糊匹配,前面加了占位符,索引失效
- or连接的条件,一侧有索引,另一侧没有,索引失效
- 如果MySQL评估,走全表扫描比走索引更快,索引失效
SQL提示
指的是执行select语句的时候,如果有很多索引,MySQL会根据内部的策略来选择使用哪个索引,此时也可以给MySQL提示,告诉它用哪个索引、忽略哪个索引、强制使用哪个索引。
覆盖前缀
查询返回的列在索引当中都包含了,不需要回表查询;回表查询指的是在查询的时候先走二级索引检索到这行数据的id,再根据id到聚集索引查询到这行的数据。
前缀索引
适用场景:当遇到一些字符串长度较长,或大文本字段时,针对它建立联合索引,缩小索引体积,提高检索效率
单列/联合索引
推荐使用联合索引,因为:联合索引性能较高,如果联合索引使用得当,可以避免回表查询
-
索引设计原则
针对哪些表建立索引?
数据量大、查询频次高
针对这些表的哪些字段建立索引?
经常在 where、order by、group by 之后出现的字段建立索引
针对于这些字段建立什么样的索引?
如果这列是唯一的,建立唯一索引,区分度高;如果能建立联合索引,尽量使用联合索引;如果涉及到字符串长度较长或者大文本字段,尽量使用前缀索引。
SQL优化
- 插入数据
- 主键优化
- order by 优化
- group by 优化
- limit 优化
- count 优化
- update 优化
插入数据
insert 优化
-
批量插入
insert into 表名 values(1,'Tom'),(2,'Cat'),(3,'GC');
如果批量插入,一次性插入的数据,不建议超过一千条;如果插入几万条数据,可以将其分割为多条insert语句。
-
手动提交事务
start transaction;
insert into 表名 values(1,'A'),(2,'B'),(3,'C');
insert into 表名 values(4,'D'),(5,'E'),(6,'F');
insert into 表名 values(7,'G'),(8,'H'),(9,'I');
commit;
-
主键顺序插入
主键乱序插入:3,8,2,77,62,10
主键顺序插入:1,2,3,10,23,77
顺序插入的性能高于乱序插入
大批量插入数据
如果一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的 load 指令进行插入。操作如下:
# 客户端连接服务端时,加上参数 --local-infile
mysql --local-infile -u root -p
# 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
set global local_infile=1;
# 执行load指令将准备好的数据加载到表结构当中
load data local infile '/root/sql1.log' into table `tb_user` fields terminated by ',' lines terminated by '\n'; -- 字段值之间使用,分割,每一行数据之间使用\n分割
主键顺序插入性能高于乱序插入
主键优化
33. 进阶-SQL优化-主键优化_哔哩哔哩_bilibili
数据组织方式
在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(IOT)。
页分裂
页可以为空,也可以填充一半,也可以填充100%。每个页包含了2~n行数据(如果一行数据过大,会行溢出),根据主键排列。
主键顺序插入:
主键乱序插入:
50该插入页1,但已满。然后页1分裂,后面数据移到页3,50接上,再重新对链表指针进行设置
页合并
当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其它记录声明使用。
当页中删除的记录达到 MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠近的页(前或后),看看是否可以将两个页合并以优化空间使用。
MERGE_THRESHOLD:合并页的阈值,可以自己设置,在创建表或者创建索引时指定。
主键设计原则
order by 优化
34. 进阶-SQL优化-order by优化_哔哩哔哩_bilibili
MySQL中的排序方式有两种: 优化尽量往using index优化
- using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。
- using index:通过有序索引顺序扫描直接返回有序数据,这种情况叫 using index,不需要额外排序,操作效率高。
总结:
-
根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。
-
尽量使用覆盖索引。
覆盖索引,不需要额外的查询;没有用到覆盖索引,需要回表查询数据,然后在排序缓冲区中对数据进行排序,排序方式为using filesort,效率低。
-
多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
-
如果不可避免地出现了filesort,大数据量排序时,可以适当增大排序缓冲区的大小 sort_buffer_size(默认256k)
group by 优化
35. 进阶-SQL优化-group by优化_哔哩哔哩_bilibili
- 在分组操作时,可以通过索引来提高效率。
- 分组操作时,索引的使用也是满足最左前缀法则的。
limit 优化
36. 进阶-SQL优化-limit优化_哔哩哔哩_bilibili
一个常见又非常头痛的问题就是 limit 2000000,10,此时需要MySQL排序前2000010记录,仅仅返回2000000~2000010的记录,其它记录丢弃,查询排序的代价非常大。
优化思路:一般分页查询时,通过创建 覆盖索引 能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。
select t.* from tb_sku t,(select id from tb_sku order by id limit 2000000,10) a where t.id=a.id;
将查询结果id当作一张表,与tb_sku表进行连接查询,取出表中对应id地数据。
count 优化
聚合函数count():统计数量
优化思路:自己计数
explain select count(*) from 表名;
count的几种用法
-
count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是null,累计值就加1,否则不加,最后返回累计值。
-
用法:count(*)、count(主键)、count(字段)、count(3)【count某一个数】
-
count(主键)
InnoDB引擎会遍历整张表,把每一行的主键id值都取出来,返回给服务层。服务层拿到主键后,直接按行进行累加计数(主键不可能为null)。
-
count(字段)
没有not null约束:InnoDB引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null,不为null,计数累加。
有not null约束:InnoDB引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接按行进行累加计数。
-
count(1)
InnoDB引擎遍历整张表,但不取值。服务层对与返回的每一行,放一个数字 1 进去,直接按行进行累加。
放什么数字不重要,0也行、-1也行
-
count(*)
InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。
-
按照效率排序:count(字段) < count(主键) < count(1) ≈ count(*),所以尽量使用count(*)
update优化(避免行锁升级为表锁)
38. 进阶-SQL优化-update优化(避免行锁升级为表锁)_哔哩哔哩_bilibili
**InnoDB的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁。**一旦升级为表锁,并发性能降低。
SQL优化总结
对于SQL优化,绝大部分情况下都是在考虑对索引进行优化
-
插入数据
insert:批量插入、手动控制事务、主键顺序插入
大批量插入:load date local infile
-
主键优化
主键长度尽可能地短、顺序插入
主键策略:auto_increment(主键自增)、UUID【推荐使用主键自增】
主键自增长度相对较短,而且是顺序插入;UUID生成的每个UUID是无序的(乱序插入可能导致也分裂现象,效率比顺序插入低)、而且长度较长
-
order by 优化
尽量使用覆盖索引,涉及到的排序字段尽量建立对应索引;排序时同为升序或降序,是可以用到索引,但如果一升一降可以用索引,但是创建索引时,需指定排序方式。
using index:直接通过索引返回数据,性能高
using filesort:需要将返回的结果在排序缓冲区排序
-
group by 优化
索引,多字段分组满足最左前缀法则
-
limit 优化
覆盖索引 + 子查询
-
count 优化
性能:count(字段) < count(主键) < count(1) ≈ count(*),所以尽量使用count(*)
-
update 优化
尽量根据主键/索引字段进行数据更新
根据索引字段更新,避免行锁升级为表锁,降低数据库的并发访问性能
视图/存储过程/触发器
视图
-
介绍
视图(View)是一种虚拟存在的表。这张表在数据库中并不实际存在,行和列的数据来自于定义视图时使用的表(基表),并且是在使用视图时动态生成的。
通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以在创建视图时,主要工作就落在创建这条SQL查询语句上。
-
创建
create [or replace] view 视图名称[(列表名称)] as select语句 [with [cascaded | local] check option]
[or replace]:替换视图
-
查询
-- 查看创建视图的语句
show create view 视图名称;
-- 查看视图数据
select * from 视图名称 ...;
-
修改
方式一:
create or replace view 视图名称[(列名列表)] as select语句 [with [cascaded | local] check option]
方式二:
alter view 视图名称[(列名列表)] as select语句 [with [cascaded | local] check option]
-
删除
drop view [if exists] 视图名称 [,视图名称] ...;
视图-检查选项
视图检查选项指的是:当我们在对视图当中的数据进行更新、插入、删除时,检查选项会去检查我们所操作的数据是否符合视图定义时的条件。
!!!不同MySQL版本之间的检查选项有不同 !!!
41. 进阶-视图-检查选项(cascaded)_哔哩哔哩_bilibili
视图-更新及作用
视图-案例
44. 进阶-视图-案例_哔哩哔哩_bilibili
存储过程
基本语法
-
创建
create procedure 存储过程名称([参数列表])
begin
-- SQL语句
end;
-
调用
call 名称([参数]);
-
查看
select * from information_schama.routines where rountine_schema='xxx'; -- 查询指定数据库的存储过程及状态信息
show create procedure 存储过程名称; -- 查询某个存储过程的定义
-
删除
drop procedure [if exists] 存储过程名称;
注意:在命令行中,执行创建存储过程的SQL时,需要通过关键字 delimiter 指定SQL语句的结束符(默认分号)。
变量
系统变量
是MySQL服务器提供,不是用户定义的,属于服务器层面。分为全局变量(global)、会话变量(session)。
-
查看系统变量
show [session | global] variables; -- 查看所有系统变量
show [session | global] variables like '...'; -- 可以通过模糊匹配方式查找变量
select @@[session | global] 系统变量名; -- 查看指定变量的值
-
设置系统变量
set [session | global] 系统变量名 = 值;
set @@[session | global] 系统变量名 = 值;