一.存储引擎
常见的存储引擎就 InnoDB、MyISAM、Memory、NDB。
InnoDB 现在是 MySQL 默认的存储引擎,支持事务、行级锁定和外键 索引的叶子节点存储的是行数据,myisam是行数据地址或者主键
InnoDB引擎的4大特性 插入缓冲 二次写 自适应哈希索引 预读
三大范式
- 1N:属性不可分割
- 2N:不存在部分依赖(针对联合主键)
- 3N:不存在传递依赖(每一列与数据表与主键直接相关)
二.索引
1.什么是索引(类似于目录)
索引是一种数据结构(计算机存储和运行的方式),协助于快速查询,更新数据等,通常是B树和B+树。 索引是一个文件,要占用物理空间。
2.索引的优缺点
2.1索引优点
加快检索速度
2.2索引缺点
时间方面:创建索引和维护索引需要消耗时间,所以当你在对表进行增删改等操作的时候,索引同时需要动态维护,降低效率。
空间方面:索引需要占物理空间,需要一个文件去记录各种索引的信息
2.3 索引的分类
按数据结构:B+tree,Hash,Full-text
按物理存储:
聚簇索引:按照每张表的主键建立一个B+树,叶子节点存放数据(数据存储和索引放到一起)
InnoDB表要求必须有聚簇索引,默认是建在主键上,没有主键的时候建在第一个非空的唯一索引上,都没有的话会自动生成一个隐式的自增id列,在此列上建立聚簇索引
非聚集索引:结构基本相同,叶子节点存放的是数据主键(我觉得是地址)
区别:
聚集索引叶子节点存放的是数据,每个表只能有一个
非聚集索引叶子节点存放的是数据主键,每个表可以有多个
按字段特性:
主键索引(primary key):建立在主键的索引,每张表只能有一个,索引列值不允许有空值
唯一索引(unique):建立在唯一字段上,每张表可以有多个,索引列值可以为空
普通索引:建立在普通字段上
全文索引:用于查找关键词
按字段个数:
单列索引:
联合索引:(I最左匹配原则)提高查询速度的同时,降低更新速度,因为他在保存数据的同时,还需要维护索引文件
2.4 索引设计原则
1.适合where子句中的列,或者连接子句
2.适合基数比较大的
3.使用短索引,如果是长字符串,可以指定一个前缀长度
例如密码,难度在于前缀截取的长度
4.不要过度索引
创建原则:最左,频繁查询,不要更新频繁,尽量拓展索引,重复值比较多的不要建
2.5 索引失效的情况
1.查询语句中,like模糊查询的时候,使用%开头
2.使用复合索引时,只有查询条件中使用了这些字段的第一个字段,索引才会使用,否则违背了最左匹配原则,会失效
3.查询语句中使用了or关键字,如果or前后的列都使用了索引,才会使用索引
4.字符串的索引字段在查询时需要用引号引用,否则索引失效
5.如果索引列上参与了计算
6.mysql觉得全表扫描会比使用索引快
2.6 创建索引三种方式
1.建表的时候创建索引
create table 表名()
2.使用alter table去增加索引(普通,unique,primary key)
alter table 表名 add index 索引名(列名,列名);
3.使用create index(普通索引,唯一索引)
create index 表名 on 索引名(列名);
2.7删除索引
alter table 表名 drop KEY 索引名
删除主键索引的时候,取消自增长,再删除
2.8 B树,B+树与hash
B树是一种自平衡树,从根节点开始,进行二分查找。键和值存放到内部节点和叶子节点,每个节点相互独立。优势在于可以把频繁访问的数据放到靠近根节点的位置
B+树搜索过程与B相同,把键放到内部节点,数据全都存储在叶子节点,使用指针顺序连接在一起,是有序的链表结构。查询性能和增删性能高于B树
哈希:
B+和hash的优劣
B+的底层是多路平衡树,从根节点出发,到内部节点的键,然后找到叶子节点的键值
hash底层是hash表,调用一次hash函数就能找到对应的一个键值,但是数据之间是没有顺序的。
由于进行hash排序之后,索引顺序与原顺序无法保持一致,导致他不可测,以及不稳定。所以他不支持索引,模糊查询,范围查询等,同时数据量大的话,会有哈希碰撞。但是一般情况下,进行等值查询的话,他可能会更快。
相比之下,B+树的结构天然就支持范围,且相对稳定
不用哈希作为索引的数据结构的原因?
1.模糊查找不支持:哈希表是把索引字段映射成对应的哈希码进行存放,如果进行模糊查询的话,只能遍历整个表。而innoDB则通过最左前缀原则快速找到对应数据
2.范围查找不支持
3.哈希冲突问题:如果很多字段恰好映射到相同的哈希码的话,会形成很长的链表,增大查找时间
2.9 怎么删除大量数据
先删除索引,然后去删除数据,再重新创建索引
三.事物
3.1 基本概念
事物是一个不可分割的数据库操作,并发的基本单位。从一种一致性状态到另一种一致性状态。要么同时成功,要么同时失败。(银行转钱)
3.2 事物四大特性(acid)
- 原子性(Atomicity):事物是最小的工作单元,不可再分
- 一致性(Consistency):执行事务前后,数据保持一致,只能同时成功或者失败
- 隔离性(Isolation):并发操作中,每个并发操作不会互相干扰
- 持久性(Durability):一但事物提交成功,事物中的所有操作持久化到数据库中
3.3 脏读虚读幻读
- 脏读:读到未提交事物的数据
- 虚读:查询两次,返回了不同的数据(另一个事物对数据进行了修改)
- 幻读:A把1》2,B又插入一个1,好像A没有修改,(新增与删除)
3.4 事物的隔离级别(基于锁和并发调度)
- 读未提交(脏,虚,幻)
- 读已提交(虚,幻)解决了脏读
- 可重复读(幻)解决了虚读(innoDB默认)
- 串行化:效率低,事物需要排队
四.锁
4.1 什么是锁
数据库有并发事务的时候,可能会产生数据不一致,需要一个访问次序的机制,他就是锁
4.2 锁的分类
4.2.1 按锁的粒度分
- 行锁(innoDB):开销大,加锁慢,会出现死锁,粒度小,冲突概率较低,并发高
- 页锁(MYISAM):开销,速度和粒度,在他们之间,并发一般
- 表锁(BDB):粒度大,冲突多,速度快
4.2.2 共享锁和排他锁
共享锁(读锁):让多个线程同时获取一个锁。由于是读,不会进行并发冲突 排他锁(写锁):一个锁在某一时刻只能被一个线程占有
4.2.3 乐观锁和悲观锁
- 乐观锁:不会发生并发冲突,在提交数据的时候,检查是否违反数据完整性。在修改的时候把事物锁起来(多读场景)
- 悲观锁:会发生并发冲突,在查询的时候就把他锁起来,直到提交事物 (多写场景)
4.3 隔离级别和锁的关系
- 读未提交:不需要共享锁,不会跟其他操作产生冲突
- 读已提交:加共享锁,在语句执行之后释放锁,
- 可重复读:加共享锁,在提交之后释放锁
- 串行化:加上锁,一直持有,直到这个事物完成
4.4 死锁
两个或者多个事物相互调用,请求锁定对方资源,形成恶性循环 4.4.1死锁产生条件 互斥条件:拿着不用,别人就用不了 请求和保持条件:有一个资源,提出新的请求,新资源被人占用 环路等待条件:A等B,B等C,C等A
4.4.1解决死锁的方法
- 如果不同程序会并发存取多个表,尽量约定相同顺序访问表
- 同一个事物,尽可能一次锁定所有所需要的资源
- 容易死锁的业务部分,尝试升级颗粒度,使用表锁
- 分布式事物锁或者乐观锁
4.5行锁怎么实现(for update)
select * from student where id = 1 for update
for update 可以根据条件来完成行表锁定,且id是索引键的列,如果id不是索引,则进行表锁
五.视图
5.1 视图的优点
- 查询简单,简化了用户操作
- 数据安全性,可以多角度看待同一数据,对机密数据进行保护
5.2 视图的缺点
- 性能,如果是多表联查,即便是很简单的查询,也会是一个结合体,花费一定时间
- 修改限制,对复杂视图来说,进行数据的修改,基本表可能修改失败。
情况: 有unique; 有group by; 有avg等聚合函数; 使用distibct关键字; 连接表视图;