索引
首先看看mysql存放数据的页
自己的总结:
数据页16kb
储存结构:
就是说数据都存放在页中 User Records中,真实情况是,都会从 Free Space 部分,也就 是尚未使用的存储空间中申请一个记录大小的空间划分到 User Records 部分,当 Free Space 部分的空间全部 被 User Records 部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新 的页了。(按照主键从小到大排序)
有默认的最小记录和最大记录
每条数据通过next_record记录下一条记录的偏移量找到下一条记录。也就是说记录与记录通过链表连接。
删除时标记 数据行delete_mask列就ok了
每个数据页形成一个双向链表
页目录:
就是说当页中记录数据过多的时候,想了一个让查询速度变快的方法。
将记录分组,n_owned 表示该组有多少记录
将每个组的最后一条记录的地址偏移量 拿出来存放到靠近页尾部分。这个部分就是 Page Directory(页目录)。这些偏移量被称为槽(slot) 。也就是说页目录由 慒 组成。(此时就可以通过二分法快速定位)
如何快速知道你要的数据在哪个页中呢?全表扫描或者索引
(设计 InnoDB 的大叔们对每个分组中的记录条数是有规定的:对于最小记录所在的分组只能有 1 条记录, 最大记录所在的分组拥有的记录条数只能在 1~8 条之间,剩下的分组中记录的条数范围只能在是 4~8 条之间。)
页头部:
一句话说 就是储存一个数据页中的状态信息,如 记录数,第一条记录地址,槽的数量
索引部分
自己的总结:
在多个页面查找数据:1.找到对应的页。 2. 从该页中找到对应的数据。
假设不用索引就只能从第一个页面 挨着往下面找。
规则:下一个数据页中用户记录的主键值必须大于上一个页中用户记录的主键值 会造成记录在页面与页面之间的移动操作。被称为页分裂。
想要在多个页面找到自己想要的页。那就给所有页面建立一个目录项。(会创建一个储存目录项记录的页)
结构:
页的用户记录中的最小的主键值,我们用 key 来表示。
页号,我们用 page_no 表示。
这种目录就被称为索引
在 InnoDB 存储引擎中, 聚簇索引 就是数 据的存储方式(所有的用户记录都存储在了 叶子节点 ),也就是所谓的索引即数据,数据即索引。
二级索引:
按照你指定索引字段排序。叶子节点储存的就是你指定的索引和主键值
索引失效场景
- 普通索引列有NULL值,条件使用is null、is not null查询
- 不适合键值较少的列,如一个列中只有5种不同,假设1w条数据 ,where type=1,就要访问2k个数据块。再加上要访问索引块 最终>2k
- 使用了前导模糊查询 like "%xx"
- 条件种有or,or条件中的列存在没有索引的列
- 联合索引 (a,b,c) where a=1 and c=1 a走索引 c不走索引 因为a相同之后按照b排序
- .如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
- 普通索引的 != ,not in , not exists不会走索引
锁
自己的总结:
mysql里面所说的锁 讲的就是内存中的一种结构
关键两个属性:trx信息 :代表这个锁结构是哪个事务生成的。 is_waiting :代表当前事务是否在等待。
粒度分:行锁,表锁
意向锁:IS,IX,对某条记录加锁之前都会对当前表加上对应的IS,IX锁。就是为了之后再给表加锁的时候判断,该表记录有没有锁。兼容就直接加,不兼容就等一下。就是说想加S锁(表锁)就要在看看有没有IX意向锁,没有才能加。 想加X锁(表锁)就要IX,IS都没有才能加
重点理解行锁:
Record Locks:给记录加锁
Gap Locks :可解决幻读问题,就是间隙锁。比如说给一条记录加上Gap Locks,该记录之前的间隙都不允许插入操作。注意这个锁仅仅就是为了解决幻读问题。如锁住1,9.锁住9 。(1,9)之间不能插入。
Next-Key Locks :既能锁住记录又能锁住间隙
Insert Intention Locks :插入意向锁。就是想往间隙中插数据的时候会被阻塞,然后给一把插入意向锁。目的就是(表明有事务想在某个间隙 中插入新记录,但是现在在等待)