什么是MySql的“回表”?如何减少回表的次数
两类索引
主键索引,其实就是聚簇索引;主键索引之外,其他的都称之为非主键索引,非主键索引也被称为二级索引,或者叫做辅助索引。
对于主键索引和非主键索引,使用的数据结构都是B+Tree,唯一的区别在于叶子节点中存储的内容不同:
主键索引的叶子节点是一行完整的数据。
非主键索引的叶子节点存储的则是主键值。叶子节点不包含行记录的全部数据;非主键的叶子节点中,除了用来排序的 key 还包含一个bookmark;该书签存储了聚簇索引的key。
所以,当我们要查询的时候:
如果是通过主键索引来查询数据,例如 select * from user where id = 1,那么此时只需要搜索主键索引的B+Tree就可以找到数据。
如果是通过非主键索引来查询数据,例如 select * from user where username = “javaboy”,那么此时需要先搜索username这一列索引的 B+Tree,搜索完成后得到的值,然后再去搜索主键索引的B+Tree,才可以得到一行完整的数据。
对于第二种查询方式而言,一共搜索了两颗 B+Tree,第一次搜索 B+Tree 拿到主键值后再去搜索主键索引的 B+Tree,这个过程就是所谓的回表。
从上面的分析我们可以看出,通过非主键索引要扫描两个 B+Tree,而通过主键索引只需要查询一颗 B+Tree,所以如果条件允许,还是建议在查询中优先选择通过主键索引进行搜索。
索引覆盖
就是把单列的非主键索引修改为多字段的联合索引,在一棵索引树上。就找到了想要的数据,不需要去主键索引树上,再去检索一边,这个现象,称之为索引覆盖。
覆盖索引即从非主键索引中就能查到的记录,而不需要查询主键索引中的记录,避免了回表的产生了树的搜索次数,显著提升性能。
例如 select age from student where name = ‘张三’;
以 name 和 age 两个字段建立联合索引
在name,age联合索引上找到名称为“张三”的节点
此时节点索引(非主键索引)里包含信息age 直接返回即可。不需要回表
使用场景
全表 count 查询优化
select count(name) from user;
给user字段增加索引,就可以利用索引覆盖提效
列表查询优化
将单列索引(name)升级为联合索引(name,sex),即可避免回表
如何创建有效的索引
1. 如果需要很长的字符串,此时需要考虑前缀索引
前缀索引即选择所需字符串的一部分前缀座位索引,这时候,需要引入一个概念叫做索引选择性,索引选择性是指不重复的索引值与数据表的记录总值的对比,可以看出索引选择性越高则查询效率越高,当选择性为1时,效率是最高的,但是在这种场景下,很明显索引选择性为1的话我们会付出很高的代价,索引会很大,这时候我们需要选择字符串的一部分前缀作为索引,通常情况下一列的前缀座位索引选择性也是很高。
计算该列完整列的选择性,使得前缀选择性接近于完整列的选择性。
2. 使用多列索引
尽量不要为多列上创建单列索引,因为这样的情况下最多只能使用一行索引,这样的话,还不如去创建一个全覆盖索引,在多列上创建单列索引大部分情况下并不能提高MySql的查询性能,MySql5.0中引入了合并索引,在一定情况下可以表内多个单列索引来定位指定的结果,但是5.0以前的版本,如果 where 中的多个条件是基于单列的索引,那么MySql是无法使用这些索引的,这种情况下,还不如使用 union。
3. 选择何松的索引列顺序
经验是将选择性最高的列放到索引最前列,可以在查询的时候过滤出更少的结果。
4. 覆盖索引
所谓覆盖索引就是指索引中包含了查询中的所有字段,这种情况下就不再需要再进行回表查询了。
5. 使用索引扫描来做排序
索引列顺序和 Order By 顺序一致
所有列的方向一致
如果关联多表,那么只有当 Order By 子句引用的字段全部为第一张表时,才能使用索引做排序,限制依然是满足索引的最左前缀需求。
6. 压缩索引
MyISAM中使用了前缀压缩技术会减少索引的大小,可以在内存中存储更多的索引,这部分优化默认也是只针对字符串的,但是可以自定义对整数做压缩。
因为前缀压缩决定了每个关键字都必须以来前面的值,所以无法使用二分查找等,只能顺序扫描,所以如果查找的是逆序那么性能可能不佳。
7. 减少重复、冗余以及未使用的索引
8. 索引和锁
InnerDB支持行锁和表锁,默认使用行锁,而MyISAM使用的是表锁,所以使用索引可以让查询锁定更少的行,这样也会提升查询的性能,如果查询中锁定了1000行,但实际只是用了100行,那么在5.1之前都需要提交事务之后才能释放这些所,5.1之后可以在服务器端过滤掉行之后就释放锁
9. 减少索引和数据碎片
首先我们要了解一下为什么会产生碎片,比如 InnerDB删除数据时,这一段空间就会被留空,如果一段时间内大量删除数据,就会导致留空的空间比实际的空间还要大,这时候如果进行新的插入操作时,MySql会尝试使用这部分空间,但是依然无法彻底占用,这样会产生碎片
产生碎片带来的后果是,降低查询性能,因为这种情况会导致随机磁盘访问
可以通过 Optimize Table 或者重新导入数据表来整理数据。
今天的文章mysql的回表_表手解决分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/53970.html