重看聚簇索引,非聚簇索引,索引覆盖,索引下推

重看聚簇索引,非聚簇索引,索引覆盖,索引下推

1. 聚簇索引和非聚簇索引

聚簇索引, 叶子节点上就是数据行. 非聚簇索引, 叶子节点仍然是索引, 但是有指针指向数据

聚簇索引非聚簇索引
叶子节点直接放了数据行数据块的指针
插入顺序数据行在物理存储空间的顺序和插入的主键顺序一致数据行存储无序
存储引擎适用于innodb适用于myisam
每个表几个因为和数据行的物理存储顺序相关, 所以只能有一个可以多个
优点1. 范围查询, 排序查询速度快. 因为本身数据行在物理存储就是有序的.
2. 由于主键索引的叶子节点和数据行在一起, 在查询到内存中时, 会以页为最小单位把页放到内存中, 再次访问同一页的相邻数据行时直接在内存中可以取到.
3. 在移动行的时候只需要维护主键索引, 辅助索引的叶子节点不用变
缺点修改和维护索引昂贵, 一旦因为数据增删导致页分裂, 叶子节点调整变化, 物理存储地址也需要迁移

聚簇索引生成:

  1. 有主键, 根据主键创建
  2. 表没有主键, 根据一个唯一非空索引创建
  3. 都没有, 创建一个隐式聚簇索引, 使用的是一个全局共享的row_id, 类型是bigint unsigned, 大小是6字节, 当溢出后会变成0

自增id在用完以后就不再变化,报主键冲突的错误

聚簇索引上建立的其他索引: 是辅助索引, 或者叫二级索引, 叶子节点保存的是主键

主键Id类型和二级索引的影响

  1. 推荐主键id采用int类型自增, 因为它通常相比varchar, char等其他类型空间更小. (int4个字节, utf-8mb4 1个字符4个字节), 数字计算也比字符串计算简单. 具体看哪一种占用空间更小
  2. 主键小一些的话,因为二级索引中保存主键, 也会减少二级索引的空间大小. 索引页越小, 加载到内存中的页也就越多. 在内存找到缓存的可能性就越大
  3. 我们应该选择最小的数据范围,因为这样可以大大减少磁盘空间及磁盘I/0读写开销

uuid和自增id

由于聚簇索引的数据行存储和主键排序有关, 所以无序的uuid在插入的时候会导致更多的页分裂和数据行迁移, 从而导致io开销, 并且在排序和区间查询的时候性能远远不如自增排序的id

但是在业务中由于自增id可能会导致泄露数据量, 以及分布式系统中保证id唯一, 方便后期分库分表

所以如果需要用uuid, 可以将其作为业务id, 但是主键ID还是推荐用自增id

2. 覆盖索引和下推索引
索引覆盖

只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表. 使用联合索引

回表

指: 在辅助索引找到主键后, 再回头拿主键去主键索引中查询对应的数据行, 多进行一遍io读取

前提

  1. select的列和where列都必须在一棵索引树上
  2. where条件的索引要符合最左前缀原则的条件, 如有个a-b-c的联合索引, 必须是a, 或a,b, 或a,b,c作为条件查询. 顺序不关心, mysql会优化

如果使用到了索引覆盖, explain执行计划中 extra的字段会返回Using index. 具体用sql演示如下

-- 对一个表 id,name,sex,age , 在name和sex建立联合索引. 这里有顺序的, 相当于是建立了name和name-sex两个索引.

-- select和where覆盖
explain select name from spring_demo.user where name = '2'; -- 使用了
-- select覆盖, where查第二个索引列
explain select name from spring_demo.user where sex = 1; -- 没有使用覆盖索引
-- select覆盖, where查第一个索引列
explain select sex from spring_demo.user where name = '2'; -- 使用了
-- select覆盖, where 按联合索引顺序查询,包含第一个索引列
explain select sex ,name from spring_demo.user where name = '2' and sex = 1; -- 使用了
-- select覆盖, where 不按联合索引顺序查询,但是包含第一个索引列
explain select sex ,name from spring_demo.user where sex = 1 and name = '2'  ; -- 使用了
-- select没有完全覆盖
explain select sex ,name,age from spring_demo.user where sex = 1 and name = '2'  ; -- 没有
-- where没有完全覆盖
explain select sex ,name from spring_demo.user where sex = 1 and name = '2' and age = 1  ; -- 没有
索引下推

索引下推是mysql5.6以后增加的优化

5.5以前. 如果要where要查询多个条件, 即便建立了联合索引, 也需要先根据其中一个条件回表查询主键索引, 再捞取出记录行来判断其他条件是否符合.

而索引下推, 会对一棵索引树中包含的where字段先筛选, 过滤掉不符合的数据, 减少回表查询的记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值