MySQL之SQL分析三部曲实际案例(六)--file sort与key_len

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: -------------------------------------------------------------------------------------------------正文-----------------------------------...
-------------------------------------------------------------------------------------------------正文---------------------------------------------------------------------------------------------------------------
问题发生于对即将上线的SQL进行review时,实际问题的截图隐去部分生产环境信息,试验环境构造于测试数据库
所有操作都是基于MySQL-5.6.26下进行的,补充实验在MySQL-5.7.9-GA环境下进行了简单验证

背景:开发人员在测试环境测试SQL时发现文件排序没有走索引
问题分析过程:下文详细描述
问题聚焦:优化器为什么没有走索引去排序,以及key_len的延伸

出问题的SQL语句(同类型的问题构造)

点击(此处)折叠或打开

  1. select * from t_order_main 
  2. where outer_order_id >= '1' and outer_order_id <= '3'
  3. and pay_time>='2014-11-11 00:00:00' and pay_time<='2014-11-11 23:59:59'
  4. order by order_id;

问题描述:开发在测试环境的表上面建立了 outer_order_id,  pay_time,  order_id的联合索引, 希望解决explain里面出现的file sort的问题,
但是加了索引以后,发现explain的输出结果中还是存在filesort,结果如下图
索引

执行计划

可以看到虽然有索引可以同时覆盖到选择条件和排序列, 但是MySQL的优化器没有选择那个联合索引,而是选择了两个where条件的联合索引
既然要看优化器的一些信息,那么就去trace里面找找吧~一组使用正常的优化器逻辑,一组使用force来指定索引,截取部分信息截图
正常的优化器选择逻辑,可以看到优化器估计的cost是2.2

强制指定索引,

索引的代价是一样的

但是在排序的时候, 这个联合索引的最后一列没有用上


从这两个对比里面很容易看出来, 优化器认为走索引去排序并不好,而且三列的联合索引和两列的联合索引都是一样的cost,自然也就不会去使用相对体积更大的三列联合索引了。
结论:MySQL对比两种索引策略的cost以后,认为使用索引去排序没有必要,所以选择了体积相对比较小的两列联合索引,
这种情况多发生于最终结果集比较小的时候,排序的操作就可以完全放在内存,而不用读索引,然后再回表取数据,所以虽然联合索引有排序列,但是MySQL并不会去使用。

延伸:有一个很有意思的现象,这两个索引的结构不一样,但是key len却是一样的,原因
对比一下强制索引和默认索引的explain,有一个比较有意思的现象:两个执行计划的key len都是103~但是这两个索引的结构是不一样的;


引用前辈的总结(出处同下面的 key len计算方式): key len表明了在这次查询中,所用到的索引的长度,所用到的,意味着,如果索引的某些列没有用到,那就不会计算在这个长度里面;
这段介绍也证实了在之前,虽然索引结构不一样,但是都只用到了一部分的索引列,那么这意味着可以通过key_len来判断实际执行中用到了多少列。
问题就变成了,这个key len是怎么算出来的?
索引对应的几个列的结构



数据结构对应的key len计算方式,一部分引用现有的资料(出处http://imysql.com/2015/10/20/mysql-faq-key-len-in-explain.shtml)

补充一个 用到的datetime的属性,计算key_len的时候为5(如果带上了小数精度,这个长度会变化,从5-8不等)
那么开始计算一下len:
outer_order_id = 32x3(UTF-8)+2(变长)=98
pay_time = 5
可以看到截图中的key_len刚好是98+5=103,说明这个执行计划使用了 outer_order_id 和 pay_time~
可是,执行计划里面真的用了pay_time?
在trace里面
我们可以看到在计算索引的代价的时候,列出了使用索引的选择条件和索引

是的,在分析索引代价的时候,没有pay_time,这说明索引中的pay_time并没有被用来优化where条件里面的逻辑,
但是key_len里面确确实实把pay_time的这一部分加上了,那么他用到哪里去了?
看看最前面截图的表结构,然后为explain增加一点额外的输出, 看看分区表的分区信息

很明显可以看到, 这个查询指向了一个单独的分区p0,真相大白~本次查询用到了pay_time,但是不是用来优化where条件的筛选,而是用在了分区条件的判断上!
作为对比,去掉pay_time的条件看看,

长度也变成了98, 分区也从p0变成了所有~

-------------------------------------------------------------------------------------------------结论---------------------------------------------------------------------------------------------------------------
MySQL会有一套Cost计算模型来判断多种索引的代价,file sort的出现,并非代表着这个语句的效率不好,因为结果集并不大的时候,纯内存的排序并不会有太高的开销,
通过走索引避免排序,然后再用随机读的方式回表反而会消耗更多的时间(随机读的开销很高
explain的key_len会反应 本次查询使用的索引的列的情况,不仅是使用在where条件里面的列,也包括判断分区条件使用到的索引列。

-------------------------------------------------------------------------------------------------附录---------------------------------------------------------------------------------------------------------------
附上其他类型的key_len的实验,请对照截图信息食用~ 测试环境MySQL-5.7.9-GA,本质上没什么区别
PS:请无视中间那个失误...
表结构

部分测试结果

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
1月前
|
存储 消息中间件 监控
MySQL 到 ClickHouse 明细分析链路改造:数据校验、补偿与延迟治理
蒋星熠Jaxonic,数据领域技术深耕者。擅长MySQL到ClickHouse链路改造,精通实时同步、数据校验与延迟治理,致力于构建高性能、高一致性的数据架构体系。
MySQL 到 ClickHouse 明细分析链路改造:数据校验、补偿与延迟治理
|
2月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
126 3
|
1月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
320 5
|
2月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
|
2月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
2月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
523 13
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
342 9
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
238 6

推荐镜像

更多