mysql优化-减少查询回表次数和回表数据量
减少数据回表常见的三种方式分别是1)查询条件使用聚集索引;2)使用索引下推;3)使用索引覆盖。
1 查询条件使用聚集索引-避免回表查询
按照索引使用数据结构B+树叶子结点是否包含表中全部字段,mysql 索引可以分为聚集索引和非聚集索引(辅助索引),聚集索引反应了记录在磁盘上存储的物理结构,辅助索引反应了记录的逻辑结构。聚集索引索引B+树叶子结点存储表所有字段属于聚集索引,查询索引可以直接获得所有字段信息,索引B+树叶子结点只存储聚集索引id,根据辅助索引查询全部字段时,首先根据辅助索引,查询到聚集索引,然后根据查询到的聚集索引id逐个回表查询记录完整信息。综上,使用聚集索引查询不用二次回表。
2 使用索引覆盖-避免回表查询
先有如下一个订单表,考虑需要经常查询某个用户购买某个商品的信息,所以设计了联合主键(user_id, spu_id)。
CREATE TABLE `order` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID', `spu_id` bigint(20) unsigned NOT NULL COMMENT 'SPUID', ... KEY `idx_userId_spuId` (`userId`,`spu_id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单';
现需要查询一个用户下的所有spu_id:
select * from `order` where `user_id` = 123456; -- 方式1,从表中查询整条记录,然后在后端代码中提取spu_idselect `spu_id` from `order` where `user_id` = 123456; -- 方式2,只查询spu_id字段
相同点是,在数据量很大情况下,两种方式都会走索引idx_userId_spuId;不同点是,方式1,先根据辅助索引找到主键id(此时聚集索引建立在主键上),然后对每个主键id进行回表查询整条记录信息,方式2,因为联合索引恰好包含查询字段spu_id,避免了二次回表查询。
3 使用索引下推-减少回表次数
下面是一个用户表,同时在用户姓名和年龄创建了一个联合索引
CREATE TABLE `user_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(512) unsigned NOT NULL COMMENT '姓名', `age` bigint(20) unsigned NOT NULL COMMENT '年龄', ... KEY `idx_name_age` (`name`,`age`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息';
先需要查询18岁以下所有姓张的同学信息(场景好奇快😂):
select * from `user_info` where name like '张' and age < 18;
在mysql 5.6 之前,查询过程使用idx_name_age索引查询主键id,然后根据主键逐个回表(没在联合索引上使用age < 8条件,是使用联合索引字段作为查询条件,遇到非等值查询联合索引后续字段会失效),同时使用age < 8条件进行过滤,回表记录可能会因为age条件而在最终结果中过滤掉,这样,其实被过滤的记录要是不用回表可以减少二次回表次数,提高查询效率。在mysql 5.7 引入「索引下推」,查询过程变成,name走索引idx_name_age,同时继续直接使用age对索引进行过滤,需要回表查询的小部分记录都会包含在最终结果里面。
note:order by 中排序字段可以和where中查询字段都被包含在联合索引中,也可能引起索引下推。
参考:
1 Mysql优化(十)什么是 MySQL 的 回表 ?怎么减少回表的次数?
2 MySQL聚集索引和非聚集索引
3 主键,聚集索引,不是一个东西!
4 Mysql性能优化:什么是索引下推?
来源地址:https://blog.csdn.net/huhu123444/article/details/130406967
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341