写在最前,本人也只是个大三的学生,如果你发现任何我写的不对的,请在评论中指出。
索引
直接提出我们需要注意的索引的问题:
- 索引为什么可以加快数据库的检索速度
- 索引为什么降低了插入、删除、修改等操作的速度
- 什么是索引的最左匹配原则
- Hash索引和B+树索引的区别是什么?
1.1 索引的基础知识
首先数据库的存储结构是页, 页与页之间会形成双向链表,方便我们遍历查找,而每个数据页中的记录又组成了一个单向链表,在通过主键查找某条数据库记录的时候可以在页目录中使用二分法快速定位,以下是它的物理存储结构:
所以说,如果写:select * from user where username = '张三'
这种没有任何优化的语句,数据库默认这么做:
- 定位到记录所在页: 需要遍历双向链表,找到对应页
- 从所在页内查找:由于不是主键,所以遍历单向链表
1.2 但是为什么索引加快了检索速度呢?
其实就和新华字典是一样的,通过新华字典的检索目录,我们能够查找对应的有序的表来查找我们所需要的字符。 索引的道理也是一样的,它也是将无序的数据变得相对有序而已。 这其实就是底层数据是B+树(但是我的数据结构学的太烂,讲不太好)
具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等——摘自百度。
B+树是平衡树的一种,不会在极端情况下退化为链表,因为树的高度都是相对较低,基本都是矮胖矮胖的那种。所以,这样我们的检索的时间复杂度就是O(logn), 但相应的,我们对B+树做增删改是会破坏它的原有结构, 要维持平衡树, 就需要额外的工作,而这么开销,就导致了删除、修改等运行速度
所以建议是不要将经常改动的属性设为索引,要好好爱惜你的B+树
1.3 哈希索引~
哈希索引就是采用了哈希算法, 不像B+树那样从根节点到叶节点逐级排查, 只需要一次哈希算法就能立刻定位,非常的快!,但是哈希索引没办法利用索引排序,不支持最左匹配,在大量重复键值的情况下,效率极低,而且不支持范围查询。 主流还是B+树索引树用的比较多
1.4 最左匹配原则
指的是:
- 如有索引a、b、c、d, 查询条件是
a = 1 and b = 1 and c >3 and d = 4
,则会在每个节点依次命中a、b、c,无法命中d。 也就是说,在遭遇到范围查询的之后就会退化为线性查询
锁
先说一点让大家放心的事, 即使你事先不了解锁的概念也不用担心, 因为数据库会隐式的帮我们加锁。我们学习数据库锁的知识是为了能够在需要的情况下派得上用处, 可以更好的把控自己的程序
2.2 锁的简单介绍
首先从锁的粒度开始讲:
- 表锁: 开销小, 加锁快;不会出现死锁;锁定力度大,发送冲突概率大,并发度最低
- **行锁:**开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高(InnoDB支持行锁)
表锁又分: 表读锁, 表写锁, 关于表锁只要记住读读不阻塞, 读写阻塞, 写写阻塞。 也就是当前用户读取数据时其他用户也在读取数据,不会加锁; 当前用户在读数据时, 其他的用户不能修改当前用户读的数据,会被加锁; 当前用户修改数据的时候,其他的用户不能修改当前用户正在修改的数据,会加锁! 另外写锁是优先于读锁的。
行锁相较于表锁要更注重一点, 因为很少加表锁(而且表锁也是自动的)
InnoDB实现了以下两种类型的行锁(另外, 事务是指对数据库进行读或写的一系列操作):
- 共享锁(读锁):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。 共享, 多个客户可以读取同一个资源,但不允许其他客户去修改。
- 排他锁(写锁): 允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁
2.3 乐观锁和悲观锁
- 乐观锁: 是一种思想, 具体实现是, 表中有一个版本字段, 第一次读的时候,获取到这个字段。处理完逻辑业务开始更新的时候, 需要再次查看该字段的值是否和第一次查询时一样。如果一样就更新,反之拒绝。之所以叫乐观锁,是因为这个模式不加锁
- 悲观锁: 是数据库层面加锁, 有阻塞。
悲观锁
简单例子: select * from XXX for update
加上后面两个单词意味着加了排他锁,加锁之后,其他事务就不能对他进行修改了!需要等待当前事务处理完。
乐观锁
不是数据库层面的锁,是需要自己手动去加的锁,一般是通过加字段版本号来实现的:
seelct * from talbe # 这个表里有version的字段
2.4 死锁
一般来说MYSQL的回滚帮助我们解决了不少死锁的问题, 虽说也无法全部避免, 但可以这样:
- 以固定的顺序访问表和行
- 大事拆小
- 在同一个事物中,尽可能一次锁定所需要的所有资源
- 降低隔离级别
- 为表添加合理的索引