存储引擎:是一个表存储/组织数据的方式。不同的存储引擎,表存储的方式不同。数据库中的各表在创建时均被指定的存储引擎来处理。这是MySQL中特有的术语,Oracle中不叫该名字。
在建表的时候可以再最后小括号")"的右边使用 ENGINE=xxx来指定存储引擎
create table t_class(
classno int primary key,
classname varchar(32)
) engine = InnoDB default charset = gbk; -- 指定默认的额存储引擎和字符编码方式
它使用三个文件表示每个表:
优点:可被转换为压缩、只读表来节省空间
缺点:不支持事务,安全性低
这是MySQL默认的存储引擎,同时也是一个重量级的存储引擎。InnoDB支持事务,支持数据库崩溃后的自动恢复机制。InnoDB最主要的特点是支持事务,以保证数据的安全。
它管理的表具有下列主要特征:
InnoDB缺点:因为安全,所以效率不是很高,并且也不能压缩,不能转换为只读,不能很好地节省空间
使用MEMORY存储引擎的表,其数据存储在内存中,且行的长度固定,这两个特点使得MEMORY存储引擎非常的快。
MEMORY存储引擎管理的表具有以下特征:
MEMORY存储引擎以前被称为HEAP引擎。
优点:查询效率是最高的
缺点:不安全,关机之后数据消失。因为数据和索引都是在内存当中。
一个事务就是一个完整的业务逻辑,是一个最小的工作单元,不可再分。
什么是一个完整的业务逻辑:
假设转账,从A账户向B账户转1000,将A账户的钱减去1000(update语句),同时将B的账户的钱加上1000(update语句),这就是一个完整的业务逻辑。
以上的操作是一个最小的工作单元,要么同时成功,要么同时失败,不可再分。
只有DML(insert、delete、update)语句才和事务有关系,其他语句和事务无关,因为只有以上的三个语句是对数据库表中数据进行增、删、改的。只要操作涉及到增、删、改,就需要考虑安全问题,数据安全是第一位的!
对事务的理解:
假设所有的业务,只要一条DML语句就能完成,就没必要存在事务机制。正是因为做某件事的时候,需要多条DML 语句共同联合完成,所以需要事务的存在。说到底,一个事务其实就是多条DML语句同时成功,或者同时失败。
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件
事务开始:insert-insert-delete-delete-update-update 事务结束!
在事务的执行过程中,每一条DML的操作都会记录到‘事务性活动的日志文件’中,我们可以提交事务,也可以回滚事务。
提交事务:清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中。提交事务标志着事务是一种全部成功的结束。
回滚事务:将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件。回滚事务标志着,事务是一种全部失败的结束。
回滚事务:
drop table t_vip if exists;
create table t_vip(
id int(5) primary key auto_increment,
name varchar(32)
);
start transaction;
insert into t_vip(name) values ('zhangsan');
insert into t_vip(name) values ('zhangsan');
insert into t_vip(name) values ('zhangsan');
select * from t_vip; --此时可以查到t_vip中有三条数据
rollback;
select * from t_vip; --此时可以查到t_vip中没有数据
提交事务:
drop table t_vip if exists;
create table t_vip(
id int(5) primary key auto_increment,
name varchar(32)
);
start transaction;
insert into t_vip(name) values ('zhangsan');
insert into t_vip(name) values ('zhangsan');
insert into t_vip(name) values ('zhangsan');
commit; --提交事务
select * from t_vip; --此时可以查到t_vip中有三条数据
rollback;
select * from t_vip; --此时依然可以查到t_vip中没有数据
select @@transaction_isolation; --查看数据库当前隔离级别(MySQL8以后)
select @@tx_isolation;--查看数据库当前隔离级别(MySQL8以前)
set global transaction isolation level read uncommitted;-- 设置全局事务的隔离级别,设置完退出重新进入才生效
索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。一张表的任何一个字段都可以添加索引,也可以多个字段联合起来添加索引,索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。
MySQL的查询方式主要有两种:①全表扫描;②根据索引检索。
注意:在实际中,汉语字典的目录是排序的,因为只有排序了才有区间的说法,缩小扫描范围就是扫描某个区间。在MySQL中的索引也是需要排序的,并且这个排序和TreeSet数据结构相同。TreeSet(TreeMap)底层是一个自平衡的二叉树!在MySQL中索引是一个B-Tree(Binary)数据结构,遵循左小右大原则存放,采用中序遍历方式遍历数据。
索引的实现原理:
NOTE:
创建索引:
create index emp_ename_index on emp(ename); -- 给emp的ename字段添加索引,起名emp_ename_index
删除索引:
drop index emp emp_ename_index on emp; --将emp表上的emp_ename_index索引对象删除
在MySQL中,如何查看一个SQL语句是否使用了索引进行检索?
explain select * from emp;
查看其中type的结果:ALL=未使用索引;ref=使用索引,也可以从扫描的行数看到。
使用:
未使用:
很多情况下,索引会失效,例如
create index emp_job_sal_index on emp(job,sal);
explain select * from emp where job = 'Manager'; --此时索引可以使用
explain select * from emp where sal = 800; -- 此时索引失效
create index emp_sal_index on emp(sal);
explain select * from emp where sal + 1 = 800; -- 此时索引失效
explain select * from emp where lower(ename) = 'smith';
索引是各种数据库进行优化的重要手段。优化的时候优先考虑的因素就是索引。索引在数据库当中分了很多类:
视图:站在不同的角度去看待同一份数据。
表复制(操作复制后的表dept2数据,原表数据不会被改变):
create dept2 as select * from dept;
创建视图对象(操作视图对象的表emp_view1数据,原表数据会被改变):
create view emp_view1 as select * from emp;
删除视图对象:
drop view emp_view1;
注意:只有DQL语句才能以view的形式创建,即
create view view_name as 这里的语句必须是DQL语句
但是视图对象完成后,可以对视图对象进行增删改查等操作。
视图的作用:
我们可以面向视图对象进行增删改查,对视图对象的增删改查,会导致原表被操作。
假设有一条非常复杂的SQL语句,而这条语句需要在不同的地方反复使用,每一次使用这个SQL语句的时候都需要重新编写,就会很长很麻烦,此时,我们可以把这条复杂的语句以视图对象的形式创建,在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发,并且利于后期的维护,因为修改的时候也只需要修改一个位置就行,只需要修改属兔对象所映射的SQL语句。
我们以后面向视图开发的时候,使用视图时可以像使用table一样。可以对视图进行增删改查(CRUD:create,retrieve(查,检索),update,delete)等操作。视图不是存在内存当中,而是存在硬盘上,不会消失。
导出:
导出整个数据库:
在windows的cmd窗口中执行(不要登录MySQL):
mysqldump world > D:\test.sql -u root -p123
导出指定的某张表:
mysqldump world emp> D:\test.sql -u root -p123
导入:
先登录MySQL后执行下面的命令:
1.创建数据库:create databases world;
2.使用数据库:use world;
- 然后初始化数据库: source D:\test.sql
数据库设计范式指的就是数据库表的设计依据,教我们更好的进行数据库表的设计。
三范式内容:
设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费。
第一范式是最核心,最重要的范式,所有表的设计都需要满足。
例如:
学生编号 | 学生姓名 | 联系方式 |
---|---|---|
1001 | 张三 | [email protected],13500000000 |
1002 | 李四 | [email protected],15899999999 |
1001 | 王五 | [email protected],18988888888 |
上面的表就不满足第一范式。没有主键,联系方式不具有原子性,还可以再分。修改为下面的表即可满足:
学生编号(pk) | 学生姓名 | 邮箱 | 联系电话 |
---|---|---|---|
1001 | 张三 | [email protected] | 13500000000 |
1002 | 李四 | [email protected] | 15899999999 |
1003 | 王五 | [email protected] | 18988888888 |
多对多,三张表,关系表两个外键!!!
第二范式建立在第一范式的基础之上,要求每个非主键字段都要完全依赖主键,不要产生部分依赖。
学生编号 | 学生姓名 | 教师编号 | 教师姓名 |
---|---|---|---|
1001 | 张三 | 001 | 王老师 |
1002 | 李四 | 002 | 赵老师 |
1003 | 王五 | 001 | 王老师 |
1001 | 张三 | 002 | 赵老师 |
这张表描述了学生和老师的关系:1个学生可能有多个老师,1个老师有多个学生,多对多关系!
上面的表既不满足第一范式,也不满足第二范式。
修改使其满足第一范式,学生编号和教师编号联合起来做主键,复合主键(PK:学生编号+教师编号)
学生编号 | +教师编号(PK) | 学生姓名 | 教师姓名 |
---|---|---|---|
1001 | 001 | 张三 | 王老师 |
1002 | 002 | 李四 | 赵老师 |
1003 | 001 | 王五 | 王老师 |
1001 | 002 | 张三 | 赵老师 |
经过修改之后,以上的表满足了第一范式,但不满足第二范式,因为张三依赖1001,王老师依赖001,显然产生了部分依赖。“张三”,“王老师”都重复了,因此产生了数据冗余,空间浪费。
为了让以上的表满足第二范式,使用三张表来表示多对多的关系!!!!
学生表:
学生编号 | 学生姓名 |
---|---|
1001 | 张三 |
1002 | 李四 |
1003 | 王五 |
教师表:
教师编号 | 教师姓名 |
---|---|
001 | 王老师 |
002 | 赵老师 |
学生教师关系表:
id(pk) | 学生编号(fk) | 教师编号(fk) |
---|---|---|
1 | 1001 | 001 |
2 | 1002 | 002 |
3 | 1003 | 001 |
4 | 1001 | 002 |
总结:多对多,三张表,关系表两个外键!!!
第三范式建立在第二范式的基础之上,要求每个非主键字段都要直接依赖主键,不要产生传递依赖。
学生编号 | 学生姓名 | 班级编号 | 班级名称 |
---|---|---|---|
1001 | 张三 | 01 | 一年级一班 |
1002 | 李四 | 02 | 一年级二班 |
1003 | 王五 | 03 | 一年级三班 |
1004 | 赵六 | 03 | 一年级三班 |
以上表的设计师描述班级和学生的关系,1对多,1个教室中有多个学生。
满足第一范式,有主键,原子性
满足第二范式,主键不是复合主键,是单一主键,没有产生部分依赖。
不满足第三范式,一年级一班依赖01,01依赖1001,产生了传递依赖。
不符合第三范式的要求,产生了数据的冗余。
可以修改为两张表:
班级表:
班级编号(PK) | 班级名称 |
---|---|
01 | 一年级一班 |
02 | 一年级二班 |
03 | 一年级三班 |
学生表:
学生编号(PK) | 学生姓名 | 班级编号(FK) |
---|---|---|
1001 | 张三 | 01 |
1002 | 李四 | 02 |
1003 | 王五 | 03 |
1004 | 赵六 | 03 |
总结:一对多,两张表,多的表加外键!!!