学习内容重点:
1.索引的本质
2.索引数据结构:二叉树,红黑树,Hash,B树,B+树详解
3.Mysql存储引擎
1.索引的本质
是帮助Mysql高效获取数据的排好序的数据结构。
举个形象的比喻:就如同书本的目录页,根据目录找到对应的内容
2.索引的数据结构
二叉树,红黑树,Hash表,B-Tree,B+Tree...
二叉树:
key-value,查找数据从根节点查找,(排序)左边的子节点小于右边的子节点
单边增长就会形成链表,查找数据慢,得依次查找
红黑树:(红黑树的书面定义不多做赘述)如果单边增长过多,会自动平衡,又叫二叉平衡树
(1.8hashMap底层数据结构就修改为数组+红黑树)
在数据量大的情况,树的高度不可控,树的高度越小,查找的次数越少
B-Tree:
没有冗余索引,每个叶子节点都包含数据,叶节点之间指针为空
所有索引元素不重复
节点中的数据索引从左到右递增排列(排好序了)
B+Tree:(B-Tree变种) MySQL采用B+树作为索引
1.非叶子节点只存储冗余索引,不存储data
2.叶子节点包含所有的索引字段,它们之间用指针连接,可以提高查询区间(一段范围内)的数据
(1)指针存放的是相邻元素的位置(磁盘地址)
(2)从根节点开始查找,将节点放到内存里(RAM)比较(用二分查找算法等高效算法),定位到非叶子节点找到对应的磁盘地址,再根据这个磁盘地址找到叶子节点对应的data
(3)其中:data跟存储引擎有关,有可能是索引所在行的文件地址,也有可能是索引所在行的其他列
(4)查看mysgl文件页大小(16K) : SHOWGLOBAL STATUS like Innodb_page_size;
一行记录很少超过1kb(如果存储的是文本类型可能就大了)
非叶子节点,假设主键ID为bigint类型,那么长度为8B(字节),指针存放地址大小在Innodb中为6B,一共就是14B,那么一页里就可以存储16K/14=1170个(主键+指针)那么一颗高度为3的B+树能存储的数据为:1170*1170*16=21902400(千万级)
(5)一般生产环境根节点常驻内存也有可能非叶子节点都放在内存,这样就减少磁盘I/O,查找的次数跟树的高度有关
(6)超过2000多万建议分库分表,或者树的高度改为4(不建议)
hash:
mysql底层还有个hash索引,在某种程度上比B+Tree快,hash运算很快
但是建立索引很少用hash,因为Hash冲突,仅能满足=,in,不支持范围查询
范围查找
B+Tree 在叶子节点有双向指针(MySQL 对B+Tree数据结构做了调整,变成双向指针),数据量大可以分页
3.存储引擎
MyISam,索引文件和数据文件是分离的(非聚集)
.frm 框架,表结构
.MYD 表数据
.MYI 索引
查询:MYI 索引文件查找,定位到某个具体元素后:根据数据(MYD文件数据的地址)去MYD文件去查找具体数
innodb(聚集/(聚簇)索引---叶节点包含了完整的数据记录)
.frm
.ibd 按照B+Tree 组织的一个索引结构文件,所在行的其他列的数据(一行数据)
二级索引:(非主键索引)(也是非聚集索引,稀疏索引),叶子节点数据存放聚集索引(有主键就是放主键),需要回表操作;非主键索引结构叶子节点存储的是主键值为了保证一致性和节省空间
联合索引:多个字段共同组合成一个索引
索引最左前缀原理:已经根据字段排好序了,如果不按顺序就会全表扫描了
为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?
如果不建主键,就会选择某一列所有数据不同的列,如果选不到就会建一个隐藏列,维护唯一的id,用这个组织整张表的数据;整型比大小快,字符串uuid用ASCII码比较很慢;
使用自增主键:新增时总是往后面新增,如果不自增就会分裂节点再平衡节点。