索引数据结构B+树
在innodb中,表都是根据主键顺序以索引的形式存放的,innodb采用B+树索引模型,索引都是存储在B+树中的
B+树的特点:
1 每个节点中子节点的个数不能超过m,也不能小于m/2
2 根节点的子节点个数可以不超过m/2
3 m叉树只存储索引,并不真正存储数据
4 通过链表将叶子节点串联起来,方便按区间查找
5 一般情况,根节点存储在内存,其他节点存储在磁盘
如果B+树的m为100,对一亿个数据构建索引,树的高度只有3,最多只需要3次磁盘io就能获取到数据
/**
* 这是 B+ 树非叶子节点的定义。
*
* 假设 keywords=[3, 5, 8, 10]
* 4 个键值将数据分为 5 个区间:(-INF,3), [3,5), [5,8), [8,10), [10,INF)
* 5 个区间分别对应:children[0]...children[4]
*
* m 值是事先计算得到的,计算的依据是让所有信息的大小正好等于页的大小:
* PAGE_SIZE = (m-1)*4[keywordss 大小]+m*8[children 大小]
*/
public class BPlusTreeNode {
public static int m = 5; // 5 叉树
public int[] keywords = new int[m-1]; // 键值,用来划分数据区间
public BPlusTreeNode[] children = new BPlusTreeNode[m];// 保存子节点指针
}
/**
* 这是 B+ 树中叶子节点的定义。
*
* B+ 树中的叶子节点跟内部结点是不一样的,
* 叶子节点存储的是值,而非区间。
* 这个定义里,每个叶子节点存储 3 个数据行的键值及地址信息。
*
* k 值是事先计算得到的,计算的依据是让所有信息的大小正好等于页的大小:
* PAGE_SIZE = k*4[keyw.. 大小]+k*8[dataAd.. 大小]+8[prev 大小]+8[next 大小]
*/
public class BPlusTreeLeafNode {
public static int k = 3;
public int[] keywords = new int[k]; // 数据的键值
public long[] dataAddress = new long[k]; // 数据地址
public BPlusTreeLeafNode prev; // 这个结点在链表中的前驱结点
public BPlusTreeLeafNode next; // 这个结点在链表中的后继结点
}
主键索引、普通索引
主键索引叶子节点存的是整行数据
普通索引叶子节点存储的是主键的值
回表
普通索引查询数据,需要根据普通索引存储的主键值,再去查询主键索引得到结果,这个过程叫做回表
索引覆盖
如果要查询的字段已经在普通索引中了,就不需要回表,这个普通索引已经覆盖到了查询请求,因此叫做索引覆盖
索引最左前缀原则
索引项是按照索引定义里面出现的字段顺序排序的,因此,对应联合索引,并不需要索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左N个字段
索引下推
市民表联合索引(name, age)
mysql> select * from tuser where name like '张 %' and age=10 and ismale=1;
这个语句在搜索索引树的时候,只能用张,找到第一个满足条件的记录。
在mysql 5.6之前,之后的流程只能一个个回表,到主机索引上找出数据行,再对比字段值
mysql5.6引入索引下推优化,可以在索引遍历的过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表的次数
索引覆盖和索引下推的区别:索引覆盖是select返回的字段有索引中的字段,索引下推是where条件有索引中的字段
innodb 锁介绍
全局锁
对整个数据库实例加锁,MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL),全局锁的典型场景是做全库逻辑备份
表级锁
mysql中表级锁有两种,一种是表锁,一种是元数据锁
表锁的语法是:lock tables … read/write,表锁在没有出现行锁时是常用的处理并发的方式
元数据锁MDL,对一个表做增删改查操作时自动加MDL读锁,对表结构做变更时会自动加MDL写锁。
行锁
对索引进行加锁












网友评论