mysql索引问题

今天在工作写项目的时候,突然发现很多地方没有加索引,然后我就去加了,查了不少资料,捡起来了不少东西,来简单聊一聊,工作中最重要的一个细节:索引

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、回表

这里如果我们这样查询:

sql 复制代码
select age from user where name='小李'

由于我们用的是辅助索引,先查辅助索引树,发现只有name,没有age,所以这个时候就得去查主键索引树(回表),又要遍历一次主键索引树。

这里就能解答我的一个疑问:

为什么不直接一个字段一个索引,而是用组合索引(多个字段),字段太少就会回表查询,除非那种单独的使用,例如我就要通过name来查询,我就只能大度给name加一个索引,然后指定使用:

use index

sql 复制代码
select * from usera use index(nameindex) where user.name='小白'

所以使用select *就会回表查询,因为没有索引有全部字段。

4、最左前缀法则:

既然是用B+树,它的叶子节点就是一个从左往右的,所以创建索引的时候,也是按照指定的顺序的。

那么我们在使用索引时,也会从左往右查询,挨个挨个命中索引,

所以我们使用索引时,必须按照创建时的顺序,从左往右使用,但凡中间少了一个,就不会使用索引。顺序可以打乱,mysql会优化掉。

5、索引下推

没有使用索引下推

使用了索引下推:

很明显,就是提前判断了辅助索索引中有的字段,提前过滤掉,减少回表判断的次数。

来首打油诗:

全值匹配我最爱,最左前缀要遵守
带头大哥不能死,中间兄弟不能断
索引列上少计算,范围之后全失效
like百分写最右,覆盖索引不写星
不等空值还有or,索引失效要少用

mysql的两个数据库引擎 MYIASM和InnoDB

MYIASM的存储结构长这样:

也就是主键索引就是一个文件。另外一个是data文件。叶子结点对应数据在data文件里的地址。

而InnoDB是这样的:

叶子结点存放数据,所以呢,主键索引和数据是存放在一块的,所以它必须要有主键,没有指定mysql会自己生成一个。

相关推荐
WangYaolove13147 分钟前
请解释Python中的装饰器是什么?如何使用它们?
linux·数据库·python
我是黄大仙27 分钟前
利用飞书多维表格自动发布版本
运维·服务器·数据库·飞书
曾经的三心草27 分钟前
Mysql之约束与事件
android·数据库·mysql·事件·约束
宋发元31 分钟前
如何使用正则表达式验证域名
python·mysql·正则表达式
WuMingf_35 分钟前
redis
数据库·redis
张某布响丸辣42 分钟前
SQL中的时间类型:深入解析与应用
java·数据库·sql·mysql·oracle
路遇晚风1 小时前
力扣=Mysql-3322- 英超积分榜排名 III(中等)
mysql·算法·leetcode·职场和发展
P.H. Infinity2 小时前
【RabbitMQ】10-抽取MQ工具
数据库·分布式·rabbitmq
zgscwxd2 小时前
thinkphp6 --数据库操作 增删改查
数据库·thinkphp6