索引模块
1.为什么要使用索引
如果数据库中数据很多,使用全表扫描就很慢了。所以索引类似字典中将部首,偏旁组合起来去查询,就能快速查询数据
2.什么样的信息能成为索引
主键、唯一键以及普通键等
3.索引的数据结构
二叉查找树、B-Tree、B+-Tree、Hash结构
MySQL不支持BitMap
4.密集索引和稀疏索引的区别
密集索引文件中的每一个搜索码值对应一个索引值,即叶子节点不但需要保存键值,还保存位于同一行记录的其他列信息,一个表只能建立一个密集索引
稀疏索引只为搜索码的某些值建立索引项,即叶子节点只保存了键位信息以及该行数据的地址,有的稀疏索引只建立了键位信息及其主键
5.两种存储引擎
(1)Myisam
在MyISAM中 不管是主键索引 唯一键索引 普通索引 其索引都属于稀疏索引
(2)innodb
在Innodb中 有且仅有一个密集索引
(1)若一个主键被定义,该主键则作为密集索引
(2)若没有主键被定义,该表的第一个唯一非空索引则作为密集索引
(3)若不满足以上条件,Innodb内部会生成一个隐藏主键(密集索引)
(3)不同的引擎建立的文件
Myisam会建立三个文件:
test1.frm 存储表的结构信息
test1.MYI 存储表的索引信息
test1.MYD 存储表的数据信息
innodb会建立两个文件
test1.frm 存储表的结构信息
test1.ibd 存储表的索引信息和数据信息
如何定位并优化慢查询sql
经验问题,根据实际情况。提出大致思路
(1)根据慢日志定位慢查询sql(慢日志就是记录执行比较慢的sql查询)
打开慢查询日志 set global slow_query_log = on
设置慢查询时间 set global long_query_time = 1
(2)使用Explain等工具分析sql
Explain关键字段:
type :若为index或all,就是全表扫描的
extra:using filesort,using temporary 这两项意味着MySQL根本不能使用索引,效率会受到重大影响。
(3)修改sql或者尽量让sql走索引
联合索引的最左匹配原则
联合索引:多列组成的索引
最左匹配原则:假设我们有两列a,b,a和b是联合索引,他的顺序是a,b,我们在where语句中调用a=? and b=?的时候就会走联合索引,如果调用where a = ?的时候也会走索引,但是当我们使用where b = ?的时候就不会走这个联合索引
成因:mysql创建复合索引的规则是首先会对复合索引的最左边,也就是索引中的第一个字段进行排序,在第一个字段排序的基础上,在对索引上第二个字段进行排序,其实就像是实现类似order by 字段1,字段2这样的排序规则,那么第一个字段是绝对有序的,而第二个字段就是无序的了,因此一般情况下直接只用第二个字段判断是用不到索引的,这就是为什么mysql要强调联合索引最左匹配原则的原因。
索引是建立得越多越好吗
(1)数据量小的表不需要建立索引,建立会增加额外的索引开销
(2)数据变更需要维护索引,因此更多的索引意味着更多的维护成本
(3)更多的索引意味着也需要更多的空间
B-Tree
1.B-Tree的定义
(1)根节点至少包含两个孩子
(2)每个节点最多有m个孩子
(3)除根节点和叶子节点外,其余每个节点都有ceil(m/2)个孩子
(4)所有叶子节点位于同一层
(5)
B+-Tree
1.B-Tree和B+-Tree的区别:
(1)非叶子节点的子树指针与关键字个数相同
(2)非叶子节点仅用来索引,数据都保存在叶子节点中
(3)非叶子节点的指针P[i],指向关键字值[K[i],K[i+1])的子树
(4)所有叶子节点均有一个链指针指向下一个叶子节点
结论:
B+树更适合用来做磁盘索引
(1)B+树的磁盘读写代价更低
(2)B+树的查询效率更加稳定
(3)B+树更有利于对数据库的扫描
Hash索引
1.为什么不使用Hash索引?
(1)仅仅能满足”=“ ,”In“,不能使用范围查询
(2)无法被用来避免数据的排序操作
(3)不能利用部分索引键查询
(4)不能避免表扫描
(5)遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高
数据库事务的四大特性
ACID
原子性
一致性:指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
隔离性:当多个用户访问同一个数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰。多个并发事务之间要隔离
持久性:一个事务一旦被提交了,那么对数据库中的数据的改变是永久性的
MyISAM与InnoDB关于锁方面的区别是什么
MyISAM默认使用的是表级锁,不支持行级锁
InnoDB默认用的是行级锁,也支持表级锁
MyISAM适合的场景:频繁执行全表count语句
对数据进行增删改的频率不高,查询非常频繁
没有事务
Innodb适合的场景:数据增删改查都相当频繁
可靠性要求比较高,要求支持事务
数据库锁的分类
按锁的粒度划分:表级锁,行级锁,页级锁
按锁级别划分:共享锁,排他锁
按加锁方式划分:自动锁、显示锁
按操作划分:DML锁、DDL锁
按使用方式划分:乐观锁、悲观锁
事务并发访问引起的问题以及如何避免 事务隔离级别
更新丢失
脏读------------------read committed级别及以上可以避免
不可重复读-----------------repeatable read级别及以上可避免
幻读--------------------------serializable事务隔离级别可避免
当前读和快照读
当前读:select...lock in share mode,select...for update,update,insert,delete
读取的是最新版本,并且读取时候还需要保证其他事务不能修改当前记录,对读取的事务加锁
快照读:不加锁的非阻塞读,select
在RR下,事务首次调用快照读的地方很关键
在RR级别下,快照读是通过MVVC(多版本控制)和undo log来实现的,当前读是通过加record lock(记录锁)和gap lock(间隙锁)来实现的。
innodb在快照读的情况下并没有真正的避免不可重复读(出现幻读,也导致了不可重复读), 但是在当前读的情况下避免了不可重复读和幻读!!!
RR如何避免幻读
next-key锁:
行锁
Gap锁