今天在工作写项目的时候,突然发现很多地方没有加索引,然后我就去加了,查了不少资料,捡起来了不少东西,来简单聊一聊,工作中最重要的一个细节:索引
mysq的存储结构
首先要聊一聊mysql的存储模式,底层使用B+树存储,它和B-(B树,多叉树)区别就是,B+树的叶子节点是相连的(双向连表)
你们刚开始一定在想,为啥要怎么干,因为mysql只会在叶子结点存储数据,也就是说,路径上都只是拿来保存路径的,用来方便查询叶子结点。
所以用B-树查询太慢了,最快也是OlogN(它是一个N叉搜索树),B+树叶子结点可以左右查询,就不需要返回上一级,然后再查询另一叶子节点。
mysql索引结构:
上面既然说了是用的B+树作为mysql的存储结构,那么它的索引肯定也是使用B+树来存储的
索引的定义就是拿来加快查询的,如何加快,就得提到算法一个词语:
空间换时间
就像java中的使用Map存储一样,直接用key去查询value,思想是一样的。(HashMap底层也是树结构哦,小老弟!)
mysql中的索引 :
1、聚簇索引(主键)
它叶子结点就存放了主键值(很明显叶子节点是一个对象,类似有一个key和一个data,key存放的就是主键值),另一个区域存的除开主键后的所有数据。
2、辅助索引(普通索引,二级索引):
而辅助索引存放的是索引字段值,主键值。
索引的使用
3、回表
这里如果我们这样查询:
sqlselect age from user where name='小李'
由于我们用的是辅助索引,先查辅助索引树,发现只有name,没有age,所以这个时候就得去查主键索引树(回表),又要遍历一次主键索引树。
这里就能解答我的一个疑问:
为什么不直接一个字段一个索引,而是用组合索引(多个字段),字段太少就会回表查询,除非那种单独的使用,例如我就要通过name来查询,我就只能大度给name加一个索引,然后指定使用:
use index
sqlselect * from usera use index(nameindex) where user.name='小白'
所以使用select *就会回表查询,因为没有索引有全部字段。
4、最左前缀法则:
既然是用B+树,它的叶子节点就是一个从左往右的,所以创建索引的时候,也是按照指定的顺序的。
那么我们在使用索引时,也会从左往右查询,挨个挨个命中索引,
所以我们使用索引时,必须按照创建时的顺序,从左往右使用,但凡中间少了一个,就不会使用索引。顺序可以打乱,mysql会优化掉。
5、索引下推
没有使用索引下推
使用了索引下推:
很明显,就是提前判断了辅助索索引中有的字段,提前过滤掉,减少回表判断的次数。
来首打油诗:
全值匹配我最爱,最左前缀要遵守
带头大哥不能死,中间兄弟不能断
索引列上少计算,范围之后全失效
like百分写最右,覆盖索引不写星
不等空值还有or,索引失效要少用
mysql的两个数据库引擎 MYIASM和InnoDB
MYIASM的存储结构长这样:
也就是主键索引就是一个文件。另外一个是data文件。叶子结点对应数据在data文件里的地址。
而InnoDB是这样的:
叶子结点存放数据,所以呢,主键索引和数据是存放在一块的,所以它必须要有主键,没有指定mysql会自己生成一个。