故障分析 | MySQL 派生表优化
来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习数据库相关编程知识。下面本篇文章就来带大家聊聊《故障分析 | MySQL 派生表优化》,介绍一下MySQL,希望对大家的知识积累有所帮助,助力实战开发!
作者:xuty
一、问题 SQL
原 SQL 如下:
select name,count(name) from bm_id a left JOIN (select TaskName from up_pro_accept_v3_bdc union all select TaskName from up_pro_accept_v3_hsjs union all select TaskName from up_pro_accept_v3_hszjj union all select TaskName from up_pro_accept_v3_hzl union all select TaskName from up_pro_accept_v3_kjyw union all select TaskName from up_pro_accept_v3_kpzzzxwx union all select TaskName from up_pro_accept_v3_qdzc union all select TaskName from up_pro_accept_v3_rsj union all select TaskName from up_pro_accept_v3_sjba union all select TaskName from up_pro_accept_v3_spk union all select TaskName from up_pro_accept_v3_test union all select TaskName from up_pro_accept_v3_wygl union all select TaskName from up_pro_accept_v3_yms union all select TaskName from up_pro_accept_v3_zjj union all select TaskName from up_pro_accept_v3w) t on a.zxi = t.TaskName group by name
这是一个统计类的 SQL,直接执行跑了好几个小时都没有结束,所以暂时不知道实际耗时,因为实在是太久了~
二、执行计划
老步骤,我们先看下执行计划,如下图:

这里 SQL 执行主要分为 2 个步骤:
-
顺序扫描每个
select * from (select * from up_pro_accept_v3_bdc) a where a.rowguid = '185c44aa-c23f-4e6f-bcd2-a38df16e2cc3'
四、SQL 优化
简单介绍了下派生表,下面我们开始尝试优化这个 SQL,步骤分 2 步:
- 解决多张派生子表
/* 改写后 SQL */ SELECT NAME ,count(NAME) FROM ( SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_bdc bdc ON bm_id.zxi = bdc.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_hsjs hsjs ON bm_id.zxi = hsjs.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_hszjj hszjj ON bm_id.zxi = hszjj.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_hzl hzl ON bm_id.zxi = hzl.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_kjyw kjyw ON bm_id.zxi = kjyw.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_kpzzzxwx kp ON bm_id.zxi = kp.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_qdzc qdzc ON bm_id.zxi = qdzc.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_rsj rsj ON bm_id.zxi = rsj.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_sjba sjba ON bm_id.zxi = sjba.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_spk spk ON bm_id.zxi = spk.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_test test ON bm_id.zxi = test.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_wygl wygl ON bm_id.zxi = wygl.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_yms yms ON bm_id.zxi = yms.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3_zjj zjj ON bm_id.zxi = zjj.TaskName UNION ALL SELECT NAME FROM bm_id LEFT JOIN up_pro_accept_v3w v3w ON bm_id.zxi = v3w.TaskName ) t GROUP BY t.name
再来看下改写后的 SQL 执行计划,发现确实如我们预想的,在子查询中可以通过索引来进行表关联(
CREATE TABLE `tmp_up` ( `taskname` varchar(500) DEFAULT NULL, KEY `idx_taskname` (`taskname`));
- 将子查询结果插入至临时表
insert into tmp_up select taskname from up_pro_accept_v3_bdc union all select taskname up_pro_accept_v3_hsjs ......
- 使用临时表代替子查询
select name,count(name) from bm_id a left JOIN (select TaskName from tmp_up )t on a.zxi = t.TaskName group by name
- 对比下查询结果是否一致
惊讶的发现改写 SQL 的结果集会多出来很多?这里可以确认走临时表的结果集是肯定没问题的,那么问题肯定出在改写 SQL 上!
回头再仔细想一下,结合小测试,发现这样改写 SQL 确实会改变语义,问题主要是出在
LEFT JOIN
,原本 bm_id 只作了一次表关联
,而改写 SQL 后,要做多次表关联
,导致最后的结果集会多出来一部分因为LEFT JOIN
而产生的重复数据。如果是
INNER JOIN
,其实就不会产生重复数据,我们也测试下,结果确实如所想,内联是没问题的~六、个人总结
这次 SQL 优化案例个人感觉是比较有难度的,很多点自己一开始也没有想到。就比如 SQL 改写,一开始以为是没有语义上的区别,直到做了测试才知道,所以啊,很多时候不能盲目自信啊。
针对这个 SQL 来说,想要直接通过改写 SQL 优化还是比较难的,当然这里说的是不改变语义的情况下,我暂时没有想到好的改写方式,也许是火候还不够。
解决方式总结有 2 个:
- 用
内联
替代左联
,然后使用上述的改写 SQL,优点是比较方便且查询速度较快
,但是结果集会变化
。 - 通过
临时表
代替子查询
,缺点是比较繁琐,需要多个步骤实现
,优点是速度也较快
且结果集不会变化
。
附录:
http://mysql.taobao.org/month...
https://blog.csdn.net/sun_ash...
https://imysql.com/node/103
https://dev.mysql.com/doc/ref...今天关于《故障分析 | MySQL 派生表优化》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
- 解决多张派生子表

- 上一篇
- 使用PyMysql调用Mysql数据库示例

- 下一篇
- 协助报表开发之 MongoDB join mysql
-
- 欢呼的手机
- 这篇文章真是及时雨啊,太全面了,很棒,码住,关注师傅了!希望师傅能多写数据库相关的文章。
- 2023-04-09 14:24:08
-
- 高大的台灯
- 很棒,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢作者分享技术贴!
- 2023-03-24 00:14:46
-
- 数据库 · MySQL | 4小时前 |
- MySQL无法启动?8个排查方法全解析
- 174浏览 收藏
-
- 数据库 · MySQL | 5小时前 |
- 主键与唯一键区别,如何选主键?
- 166浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL多表连接优化技巧与实战策略
- 221浏览 收藏
-
- 数据库 · MySQL | 19小时前 |
- MySQL排序优化与性能提升技巧
- 153浏览 收藏
-
- 数据库 · MySQL | 21小时前 |
- MySQL中WHERE与HAVING的区别详解
- 340浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL排序优化与性能提升技巧
- 368浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL连接池配置与优化方法
- 297浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQLGROUPBY使用技巧与常见问题
- 306浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL缓存优化技巧分享
- 392浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL安装到D盘教程及路径设置详解
- 279浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL缓存设置及查询作用解析
- 470浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 96次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 89次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 107次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 98次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 98次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览