一则 MySQL 子查询改写 SQL 优化小案例
一篇短小精悍的 SQL 优化案例!
作者:马文斌,MySQL/Redis 爱好者~
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 600 字,预计阅读需要 2 分钟。
事情是这样的
近日开发那边又丢了一条 SQL 过来,查询 9 秒,看看有什么优化建议。作为 DBA,优化 SQL 乃是祖传技能,咱们就不废话,直接干他!
原 SQL
原 SQL 查询竟然需要 9 秒出结果......
SELECT
a.id,
a.order_no,
a.line_no,
a.customer_code,
a.customer_name,
a.cost_item,
a.cost_item_name,
a.payee_type,
a.payee_code,
a.payee_name,
a.tax_plan,
a.expenses_amount,
a.pre_tax_amount,
a.tax_amount,
a.start_date,
a.end_date,
a.accrued_amount,
a.paid_amount,
a.reimbursed_amount,
a.is_close,
a.payment_type,
a.settlement_date,
a.source_order_no,
a.source_order_line,
a.invoice_type,
a.del_flag,
a.create_time,
a.create_by_id,
a.create_by,
a.update_time,
a.update_by_id,
a.update_by,
a.remark,
a.shop_code,
a.close_reason,
a.close_content,
a.budget_period,
a.shop_name,
a.product_category_code,
a.product_category_name,
a.product_code,
a.product_name,
a.product_path_code,
a.shop_classify_name,
a.shop_level_require,
a.strategy_code,
a.product_path_name
FROM
expense_application_detail a
LEFT JOIN expense_application b ON a.order_no = b.order_no
AND b.del_flag = 0
WHERE
a.del_flag = 0
AND b.data_source = 8
AND b.order_type = 'B2BFYSQ01'
AND b.order_status IN (3, 8)
AND a.is_close = 0
AND EXISTS (
SELECT
1
FROM
expense_application_detail d1
LEFT JOIN base_customer_info c1 ON d1.customer_code = c1. CODE
AND c1.del_flag = 0
LEFT JOIN budget_system_ecommerce_channel d ON d. CODE = c1.business_channel_code
AND d.del_flag = 0
WHERE
d1.order_no = a.order_no
AND d.del_flag = 0
AND d.business_category_code = '01'
AND (
d.business_mode_code = '33'
OR (
d.business_mode_code = 'C010106'
AND d. CODE = 'C01010602'
)
)
);
执行计划
执行计划看 type 都是最优了,难道不能再优化了吗?不,仔细分析下还是有的。
优化思路
减少不必要的 JOIN 和子查询引用。
子查询中的 expense_application_detail
表与外部查询中的 a
表是同一张表,尝试 将子查询条件提到外面和驱动表 JOIN ,避免 EXISTS 子查询 expense_application_detail
表的重复扫描。
优化后 SQL
优化后 SQL 只需要 0.2 秒出结果,效率了提高几个数量级!
SELECT
a.id,
a.order_no,
a.line_no,
a.customer_code,
a.customer_name,
a.cost_item,
a.cost_item_name,
a.payee_type,
a.payee_code,
a.payee_name,
a.tax_plan,
a.expenses_amount,
a.pre_tax_amount,
a.tax_amount,
a.start_date,
a.end_date,
a.accrued_amount,
a.paid_amount,
a.reimbursed_amount,
a.is_close,
a.payment_type,
a.settlement_date,
a.source_order_no,
a.source_order_line,
a.invoice_type,
a.del_flag,
a.create_time,
a.create_by_id,
a.create_by,
a.update_time,
a.update_by_id,
a.update_by,
a.remark,
a.shop_code,
a.close_reason,
a.close_content,
a.budget_period,
a.shop_name,
a.product_category_code,
a.product_category_name,
a.product_code,
a.product_name,
a.product_path_code,
a.shop_classify_name,
a.shop_level_require,
a.strategy_code,
a.product_path_name
FROM
expense_application_detail a
LEFT JOIN expense_application b ON a.order_no = b.order_no
AND b.del_flag = 0
WHERE
a.del_flag = 0
AND b.data_source = 8
AND b.order_type = 'B2BFYSQ01'
AND b.order_status IN (3, 8)
AND a.is_close = 0
AND EXISTS (
SELECT 1
FROM base_customer_info c1
LEFT JOIN budget_system_ecommerce_channel d ON c1.business_channel_code = d.code
AND d.del_flag = 0
WHERE c1.code = a.customer_code
AND c1.del_flag = 0
AND d.business_category_code = '01'
AND (
d.business_mode_code = '33'
OR (d.business_mode_code = 'C010106' AND d.code = 'C01010602')
)
);
总结
在原始查询中,expense_application_detail
表被多次引用,一次在主查询中,另一次在嵌套的 EXISTS 子查询中。这种结构可能导致数据库引擎多次扫描相同的表,即使是在同一个查询中。
优化思路:减少不必要的 JOIN 和子查询引用
子查询中的 expense_application_detail
表与外部查询中的 a
表是同一张表,可以尝试将子查询条件提到外面和驱动表进行 JOIN,就可以避免 EXISTS 子查询 expense_application_detail
表的重复扫描。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
✨ Github:https://github.com/actiontech/sqle
📚 文档:https://actiontech.github.io/sqle-docs/
💻 官网:https://opensource.actionsky.com/sqle/
👥 微信群:请添加小助手加入 ActionOpenSource

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
结合RNN与Transformer双重优点,深度解析大语言模型RWKV
本文分享自华为云社区《【云驻共创】昇思MindSpore技术公开课 RWKV 模型架构深度解析》,作者:Freedom123。 一、前言 Transformer模型作为一种革命性的神经网络架构,于2017年由Vaswani等人 提出,并在诸多任务中取得了显著的成功。Transformer的核心思想是自注意力机制,通过全局建模和并行计算,极大地提高了模型对长距离依赖关系的建模能力。但是Transformer在处理长序列时面临内存和计算复杂度的问题,因为其复杂度与序列长度呈二次关系一直为业内人员所诟病。今天我们学习的RWKV,它作为对Transformers模型的替代,正在引起越来越多的开发人员的关注。RWKV模型以简单、高效、可解释性强等特点,成为自然语言处理领域的新宠。下面让我们一起来学习RWKV模型。 二、RWKV简介 RWKV(Receptance Weighted Key Value)是一个结合了RNN与Transformer双重优点的模型架构,由香港大学物理系毕业的彭博首次提出。其名称源于其 Time-mix 和 Channel-mix 层中使用的四个主要模型元素:R(Rece...
-
下一篇
openEuler:智能算力时代的数字基础设施底座
6 月 22 日,由开源中国主办,华为、上海浦东软件园联合主办的【云技术专场】OSC源创会 · 上海站 · 104期线下沙龙成功举办。华为2012实验室openEuler架构师高贵锦发表《openEuler:智能算力时代的数字基础设施底座》主题演讲,介绍了openEuler 24.03 在云原生与AI领域的最新进展,同时分享了关于如何与云原生技术共同打造更好的大模型时代的IT基础设施层平台的实践和思考,以及下一步计划。 以下为高贵锦的演讲回顾,内容由活动现场参会嘉宾@阿维同学贡献。 整理:阿维同学(WeChat:AWTX550W) OpenEuler@2024项目在2024年成功推出了多个长期支持(LTS)版本,标志着其在智能技术领域的全新篇章,并致力于构建全球性的开源新生态。以下是该项目的主要内容和成就概览: 版本发布与贡献 20.03 LTS多样性算力版本:该版本吸引了60位成员和3630名贡献者,展示了 openEuler 在多样性算力领域的强大实力。 22.03 LTS全场景版本:这个版本拥有330位成员和8403名贡献者,装机量达到130万,并推出了151个社区创新项目。 2...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Crontab安装和使用
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS6,7,8上安装Nginx,支持https2.0的开启