MySQL之SQL分析三部曲实际案例(三)--limit的陷阱

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 附上MySQL之SQL分析三部曲地址http://blog.itpub.net/29510932/viewspace-1709732/ 姐妹篇http://blog.
附上MySQL之SQL分析三部曲地址http://blog.itpub.net/29510932/viewspace-1709732/

姐妹篇http://blog.itpub.net/29510932/viewspace-1732876/ (其实是难兄难弟篇)

-------------------------------------------------------------------------------------------------正文---------------------------------------------------------------------------------------------------------------

由于是生产环境下进行的,截图和SQL都隐去了一些信息

背景:有用户在抱怨生产系统上,某一个Web的页面太慢,忍无可忍
问题分析过程:略
问题聚焦:最终确定是某一个SQL语句太慢,查询时间用了4s(慢查询日志给出的信息)

点击(此处)折叠或打开

点击(此处)折叠或打开

  1. select *
  2. from tom
  3. inner join toa on tom.order_id=toa.order_id
  4. left join tov on tom.order_id=tov.order_id
  5. left join fo on tom.sale_type=2 and fo.order_id=tom.order_id
  6. WHERE(tom.pay_time>='2015-06-23 11:45:55.869' and tom.pay_time<='2015-07-23 11:45:55.869' and tom.shop_idin(1,2and tom.buyer_nick='你们真是够了23333')
  7. order by tom.pay_time desc
  8. limit 0,20


SQL分析三部曲之一:explain,结果如下图


OMG, 明显有pay_tim和shop_id的联合索引,为什么要用pay_time的单列索引,简单验证下联合索引的执行计划



和案例一非常相似的情形,明明可以使用联合索引的地方,却使用了单列的索引,导致了预估的行数非常之高, 那么,会和案例一一样是因为统计信息的不全,导致了错误的执行计划么?

PS:案例一的情况,在没有进行任何数据库层面改动的前提下,仅仅是睡了个午觉,执行计划就变回正确的了,所以当时候判定为统计信息的问题。

然而残酷的事实就是:不管analyze table多少次,执行计划也没有改变,(没有optimize table的权限...)

SQL分析三部曲之三:optimizer_trace,操作过程略,部分结果如图


可以看到和案例一类似,由于limit的存在,导致执行计划发生了变化,但是和案例一不同的是, 这个SQL里面,limit和row_estimate的值相差的非常远!

PS:案例一中为40和51

值得注意的是,limit的数量也会影响到执行计划的选择, 比如说,limit的行数小于执行计划的row_estimate的时候,优化器会认为当前执行计划搜索出了太多的结果,进行了无谓的磁盘IO,所以会重新考虑执行计划。

在本例中, 由于在limit之前带上了order by,而且order by的列本身还是具备索引,因此,在优化器的判断逻辑中就出现了如下的一种情形:可以使用pay_time索引列,从尾部开始读取数据,然后取出前20行结果组装成结果集。所以优化器重新选择了使用pay_time的单列索引作为执行计划(这也是其他的索引均显示了“not_applicable”的原因)。

案例一的真相还原:为什么睡个午觉,执行计划就正常了?
由于在某个时间点重新统计了表的信息,行数的估计值产生了变化, 导致limit和row_estimate的大小关系发生了变化,结果就是row_estimate的值小于了limit,自然也就不会存在 rechecking_index_usage了。

在这里简单的修改了几处条件来验证之前的结论,
条件修改一:使用ignore index(idx_pay_time)
预计:如果order by的列本身并没有索引,那么在recheck里面也就没有其他的执行计划可选了,最终应该选择range_scan中的联合索引

从执行计划中可以看到idx_pay_time已经ignore了,最终执行计划选择range_scan中的联合索引


看看trace的信息

在recheck中根本就没有可选索引,所以执行计划并没有改变

条件修改二:增加limit数量直至超过row_estimate
预计:不会有recheck,执行计划采用联合索引
查看explain和trace

recheck无内容


条件修改三:去掉order by
预计:recheck无可选条件,使用联合索引



意外的收获:采用其他的索引列进行order by(仅以此献给能坚持看完这么长的内容的米娜~)
预计:执行计划采用其他的单列索引

trace内容




由于order by的原因,执行计划使用的索引又变了.... 究竟这么变是好是坏?(有生之年系列+1,今天实在是写不动了)

写在最后: 遇上order by+limit的时候,要么就用联合索引把where条件和order by的列全部包进去,要么就不要在order by的那一列上面建立单独的索引

PS:从字面上看,merge_index的特性也许会有奇效也说不定......(有生之年系列+1,天天在挖坑来坑自己.........~( ̄ε(# ̄)╰╮o( ̄皿 ̄///))
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
25天前
|
SQL 关系型数据库 MySQL
mysql一条sql查询出多个统计结果
mysql一条sql查询出多个统计结果
15 0
|
7天前
|
SQL 自然语言处理 数据库
NL2SQL实践系列(2):2024最新模型实战效果(Chat2DB-GLM、书生·浦语2、InternLM2-SQL等)以及工业级案例教学
NL2SQL实践系列(2):2024最新模型实战效果(Chat2DB-GLM、书生·浦语2、InternLM2-SQL等)以及工业级案例教学
NL2SQL实践系列(2):2024最新模型实战效果(Chat2DB-GLM、书生·浦语2、InternLM2-SQL等)以及工业级案例教学
|
11天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
38 3
|
15天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
17天前
|
SQL 数据库 索引
SQL索引失效原因分析与解决方案
SQL索引失效原因分析与解决方案
22 0
|
18天前
|
SQL 存储 关系型数据库
【MySQL实战笔记】02.一条SQL更新语句是如何执行的-2
【4月更文挑战第5天】两阶段提交是为确保`redo log`和`binlog`逻辑一致,避免数据不一致。若先写`redo log`, crash后数据可能丢失,导致恢复后状态错误;若先写`binlog`,crash则可能导致重复事务,影响数据库一致性。一天一备相较于一周一备,能缩短“最长恢复时间”,但需权衡额外的存储成本。
16 1
|
25天前
|
SQL 关系型数据库 MySQL
【MySQL】慢SQL分析流程
【4月更文挑战第1天】【MySQL】慢SQL分析流程
|
15天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
52 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
25天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
17 0