MySQL篇-SQL优化实战-减少子查询

news2024/12/26 10:58:01

回顾

上一篇了解了分析SQL使用的explain,可以点击查看MySQL篇-SQL优化实战了解我在写sql的注意事项还有explain的说明,这次拿一段生产使用的sql进行优化说明。从14s优化到2.6s

待优化的SQL

SELECT DISTINCT
	swpe.tag_number,
	hca.ACCOUNT_NAME customer_name,
	sipa.PIN_LOGO area_number,
	cdla.delivery_header_id,
	swpe.pack_number,
	swph.packslip_number,
	cdpa.transport_mode,
	date_format(
	    swpe.inware_date,
	    '%Y-%m-%d %H:%i:%s'
	) in_warehouse_date,
	DATE(cdla.act_delivery_date) act_delivery_date,
	cdla.plate_number,
    wbp.PLATFORM_NAME schedule_stage_mir,
    sooh.order_number,
    swph.lot_number,
    milk.ATTRIBUTE14,
    ifnull(
        (
            SELECT
                'Y'
            FROM
                cwms_delivery_attachment_all cda
            WHERE
                cda.pack_entity_id = swpe.pack_entity_id
            AND cda.stock_scan_status = 'Y'
            LIMIT 1
        ),
        'N'
    ) stock_status,
    ifnull(
        (
            SELECT
                cda.comments
            FROM
                cwms_delivery_attachment_all cda
            WHERE
                cda.pack_entity_id = swpe.pack_entity_id
            LIMIT 1
        ),
        NULL
    ) comments,
	 ifnull(
	    (
	        SELECT
	            swdh.delivery_number
	        FROM
	            sfy_wsh_delivery_lines_all swdl
	        INNER JOIN sfy_wsh_delivery_headers_all swdh ON swdl.delivery_header_id = swdh.delivery_header_id
	        WHERE
	            swpe.tag_number = swdl.tag_number
	        LIMIT 1
	    ),
	    NULL
	) delivery_number,
	 ifnull(
	    (
	        SELECT
	            filter1
	        FROM
	            eos_dict_entry
	        WHERE
	            DICTTYPEID = 'AUTH_CONFIG'
	        LIMIT 1
	    ),
	    'Y'
	) zc_power,
	 ppl.PICK_NUMBER pd_number,
	
	IF (
	    ifnull(
	        (
	            SELECT
	
	            IF (
	                substr(father.license_number, 1, 2) = 'TP',
	                father.license_number,
	                NULL
	            ) tp_number
	            FROM
	                wms_mtl_onhand_quantities_detail child
	            INNER JOIN wms_mtl_onhand_quantities_detail father ON child.parent_mq_id = father.mq_id
	            WHERE
	                child.license_number = swpe.tag_number
	            LIMIT 1
	        ),
	        1
	    ) != 1,
	    (
	        SELECT
	
	        IF (
	            substr(father.license_number, 1, 2) = 'TP',
	            father.license_number,
	            NULL
	        ) tp_number
	        FROM
	            wms_mtl_onhand_quantities_detail child
	        INNER JOIN wms_mtl_onhand_quantities_detail father ON child.parent_mq_id = father.mq_id
	        WHERE
	            child.license_number = swpe.tag_number
	        LIMIT 1
	    ),
	    (
	        SELECT
	
	        IF (
	            substr(
	                oldfather.license_number,
	                1,
	                2
	            ) = 'TP',
	            oldfather.license_number,
	            NULL
	        ) tp_number
	        FROM
	            wms_mtl_onhand_quantities_detail child
	        INNER JOIN wms_mtl_onhand_quantities_detail father ON child.parent_mq_id = father.mq_id
	        INNER JOIN wms_mtl_onhand_quantities_detail oldfather ON father.parent_mq_id = oldfather.mq_id
	        WHERE
	            child.license_number = swpe.tag_number
	        LIMIT 1
	    )
	) tp_number,
	
	IF (
	    (
	        SELECT
	            DOWNRACKSTYPE
	        FROM
	            wms_mtl_onhand_quantities_detail
	        WHERE
	            license_number = swpe.tag_number
	        LIMIT 1
	    ) = 3,
	    'Y',
	    'N'
	) type,
	 (
	    SELECT
	        TC_NUMBER
	    FROM
	        cwms_mobile_tray_lines cmtl
	    WHERE
	        cmtl.TAG_NUMBER = swpe.tag_number
	    ORDER BY
	        CREATION_DATE DESC
	    LIMIT 1
	) tc_number,
	
	IF (
	    (
	        SELECT
	            DOWNRACKSTYPE
	        FROM
	            wms_mtl_onhand_quantities_detail
	        WHERE
	            license_number = swpe.tag_number
	        LIMIT 1
	    ) = 3,
	    1,
	    0
	) is_scan
FROM
    cwms_delivery_lines_all cdla
INNER JOIN hz_cust_accounts hca ON cdla.customer_id = hca.cust_account_id
INNER JOIN sfy_oe_order_headers_all sooh ON sooh.oe_header_id = cdla.oe_header_id
INNER JOIN sfy_wsh_pack_entities swpe ON cdla.oe_header_id = swpe.oe_header_id
INNER JOIN sfy_wsh_packslip_headers_all swph ON swpe.header_id = swph.header_id
INNER JOIN cwms_delivery_plan_all cdpa ON cdpa.DELIVERY_HEADER_ID = cdla.DELIVERY_HEADER_ID
LEFT JOIN mtl_secondary_inventories msit ON msit.organization_id = swpe.organization_id
AND msit.secondary_inventory_name = swpe.subinventory_code
LEFT JOIN pick_pack_link ppl ON ppl.TAG_NUMBER = swpe.TAG_NUMBER
LEFT JOIN mtl_item_locations_kfv milk ON swpe.LOCATOR_ID = milk.INVENTORY_LOCATION_ID
AND milk.ENABLE_FLAG = 1
LEFT JOIN sfy_inv_pd_agent sipa ON sipa.CUST_ACCOUNT_ID = hca.CUST_ACCOUNT_ID
AND sipa.ORGANIZATION_ID = swpe.ORGANIZATION_ID
LEFT JOIN (
    SELECT
        DELIVERY_HEADER_ID,
        SCHEDULE_STAGE,
        group_concat(CAR_NUMBER) CAR_NUMBER,
        group_concat(DISTINCT LOGISTIC_PROVIDER) LOGISTIC_PROVIDER
    FROM
        wms_delivery_car_detail
    GROUP BY
        DELIVERY_HEADER_ID
) wdcd ON cdpa.DELIVERY_HEADER_ID = wdcd.DELIVERY_HEADER_ID
LEFT JOIN wms_bill_platform wbp ON wbp.PLATFORM_CODE = wdcd.SCHEDULE_STAGE
AND wbp.PLATFORM_ENABLE_FLAG = 1
WHERE
    swpe.tag_number IS NOT NULL
AND swpe.pack_number IS NOT NULL
AND swpe. STATUS != 'X'
AND cdpa.approve_status = 'Y'
AND cdpa.inv_approve_status = 'Y'
AND hca.account_number = 'GPS21017802'
AND cdla.act_delivery_date = '2024-06-26'
AND ifnull(
    swpe.delivery_date,
    cdla.act_delivery_date
) >= cdla.act_delivery_date
ORDER BY
    milk.CONCATENATED_SEGMENTS

1、问题展示

查询效率:3w条数据,耗费14s
执行结果
优化前的执行计划

2、问题排查

2.1、操作思路

通过执行计划看到wms_delivery_car_detail的执行计划好像有优化空间,先将这张表的关联移除后查看执行效率,以确认这张表影响的程度
第一次执行计划分析

2.2、执行结果

查询效率13.9s,发现移除后并没有显著的提高,说明这个子查询的执行计划并没有 很大的效率问题
移除关联子查询的执行结果

3、大胆假设,小心求证

3.1、操作思路

那么接下来看看其他执行计划,发现而且在字段上的子查询有很多,假如我们把所有字段中的子查询都移除了会有什么效果——移除了执行计划中select_type=DEPENDENT SUBQUERY的子查询后,只需要1.3s就拿到查询结果了,执行计划如图所示,由此可知字段上的子查询多了,结果集大时会对查询效率有很大的影响。
移除DEPENDENT SUBQUERY的子查询后的查询结果
移除DEPENDENT SUBQUERY的子查询后的执行计划
既然找到了问题出现在子查询上,但这些字段还是要查的,只是我们得换种方式,目的是移除子查询的情况下依然查询所需字段,那就要修改为连接查询的方式,如先把关联相同表的多个子查询通过表关联的方式合并为一次关联。

3.2、子查询分析

子查询表对应的子查询数量代码行数
cwms_delivery_attachment_all2个第21至28,34至40
wms_mtl_onhand_quantities_detail2个第86至95,100至112,115至132,138至144
sfy_wsh_delivery_headers_all1个第55至62
cwms_mobile_tray_lines 1个第150至158(因为其中的tag_number是唯一的,经业务确认此处的order by可移除)

3.3、执行结果

修改为连接查询后,查询耗时仅需要2.6s,执行计划如下:
修改后的执行结果
最后的执行计划

-- 修改后的sql
SELECT DISTINCT
    swpe.tag_number,
    hca.ACCOUNT_NAME customer_name,
    sipa.PIN_LOGO area_number,
    cdla.delivery_header_id,
    swpe.pack_number,
    swph.packslip_number,
    cdpa.transport_mode,
    date_format(
        swpe.inware_date,
        '%Y-%m-%d %H:%i:%s'
    ) in_warehouse_date,
    DATE(cdla.act_delivery_date) act_delivery_date,
    wbp.PLATFORM_NAME schedule_stage_mir,
    sooh.order_number,
    swph.lot_number,
    milk.ATTRIBUTE14,
    ifnull(cdaa.stock_scan_status, 'N') stock_status,
    ifnull(cdaa.comments, NULL) comments,
    ifnull(swdh.delivery_number, NULL) delivery_number,
    ifnull(
        (
            SELECT
                filter1
            FROM
                eos_dict_entry
            WHERE
                DICTTYPEID = 'AUTH_CONFIG'
            LIMIT 1
        ),
        'Y'
    ) zc_power,
    ppl.PICK_NUMBER pd_number,
    IF (
        -- wmoqd.TP_NUMBER是原关联fater.license_number或者oldfather.license_number的值
        substr(wmoqd.TP_NUMBER, 1, 2) = 'TP',
        wmoqd.TP_NUMBER,
        NULL
    ) tp_number,
    IF (wmoqd.DOWNRACKSTYPE = 3, 'Y', 'N') type,
    cmtl.TC_NUMBER tc_number,
    IF (wmoqd.DOWNRACKSTYPE = 3, 1, 0) is_scan
FROM
    cwms_delivery_lines_all cdla
INNER JOIN hz_cust_accounts hca ON cdla.customer_id = hca.cust_account_id
INNER JOIN sfy_oe_order_headers_all sooh ON sooh.oe_header_id = cdla.oe_header_id
INNER JOIN sfy_wsh_pack_entities swpe ON cdla.oe_header_id = swpe.oe_header_id
INNER JOIN sfy_wsh_packslip_headers_all swph ON swpe.header_id = swph.header_id
INNER JOIN cwms_delivery_plan_all cdpa ON cdpa.DELIVERY_HEADER_ID = cdla.DELIVERY_HEADER_ID
LEFT JOIN mtl_secondary_inventories msit ON msit.organization_id = swpe.organization_id
    AND msit.secondary_inventory_name = swpe.subinventory_code
LEFT JOIN pick_pack_link ppl ON ppl.TAG_NUMBER = swpe.TAG_NUMBER
LEFT JOIN mtl_item_locations_kfv milk ON swpe.LOCATOR_ID = milk.INVENTORY_LOCATION_ID
    AND milk.ENABLE_FLAG = 1
LEFT JOIN sfy_inv_pd_agent sipa ON sipa.CUST_ACCOUNT_ID = hca.CUST_ACCOUNT_ID
    AND sipa.ORGANIZATION_ID = swpe.ORGANIZATION_ID
LEFT JOIN (
    SELECT
        DELIVERY_HEADER_ID,
        SCHEDULE_STAGE,
        group_concat(CAR_NUMBER) CAR_NUMBER,
        group_concat(DISTINCT LOGISTIC_PROVIDER) LOGISTIC_PROVIDER
    FROM
        wms_delivery_car_detail
    GROUP BY
        DELIVERY_HEADER_ID
) wdcd ON cdpa.DELIVERY_HEADER_ID = wdcd.DELIVERY_HEADER_ID
LEFT JOIN wms_bill_platform wbp ON wbp.PLATFORM_CODE = wdcd.SCHEDULE_STAGE
    AND wbp.PLATFORM_ENABLE_FLAG = 1
-- 主要改动在这里:从子查询迁移到下面左关联
LEFT JOIN cwms_delivery_attachment_all cdaa ON cdaa.PACK_ENTITY_ID=swpe.PACK_ENTITY_ID
LEFT JOIN wms_mtl_onhand_quantities_detail wmoqd ON wmoqd.LICENSE_NUMBER=swpe.TAG_NUMBER AND wmoqd.ORGANIZATION_ID=swpe.ORGANIZATION_ID
LEFT JOIN sfy_wsh_delivery_lines_all swdl ON swdl.TAG_NUMBER=swpe.TAG_NUMBER
LEFT JOIN sfy_wsh_delivery_headers_all swdh ON swdh.DELIVERY_HEADER_ID=swdl.DELIVERY_HEADER_ID
LEFT JOIN cwms_mobile_tray_lines cmtl ON cmtl.TAG_NUMBER=swpe.TAG_NUMBER
WHERE
    swpe.tag_number IS NOT NULL
AND swpe.pack_number IS NOT NULL
AND swpe. STATUS != 'X'
AND cdpa.approve_status = 'Y'
AND cdpa.inv_approve_status = 'Y'
AND hca.account_number = 'GPS21017802'
AND cdla.act_delivery_date = '2024-06-26'
AND ifnull(
    swpe.delivery_date,
    cdla.act_delivery_date
) >= cdla.act_delivery_date
GROUP BY swpe.TAG_NUMBER
ORDER BY
    milk.CONCATENATED_SEGMENTS

总结

  1. 当结果集字段中有好几个相同表的子查询时,将子查询修改为连接查询的效率提升会比较大(相当于一行记录处理一次查询)
  2. 有时候执行计划可能无法直接看出修改哪里能提升,但能给我们提供优化的思路
  3. 在执行计划中看到每个表都走索引了,但是却还是很慢,那我们可以一段一段的、一表一表的排除,找到问题点在哪,而多快能找到主要就取决于经验还有对表的熟悉程度了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1893517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

精准定位推广盲点?Xinstall数据监测让每一分投入都见成效!

在这个数字化时代,App的推广早已不再是简单的“上线即成功”。面对激烈的市场竞争和日益挑剔的用户,如何精准监测推广数据,优化营销策略,成为了每个开发者与营销人员不得不面对的挑战。而在这个关键时刻,Xinstall作为一…

AI 驱动的数据中心变革与前景

文章主要探讨了AI计算时代数据中心的转型,涉及计算技术的多样性、规格尺寸和加速器的发展、大型语言模型(LLM)的发展、功耗和冷却趋势、基准测试的重要性以及数据中心的发展等方面。为大家提供深入了解AI基础设施发展的视角。 计算技术的多样…

Python 程序打印图案“G”(Python Program to print the pattern ‘G’)

在本文中,我们将学习如何使用星号和空格打印图案 G。给定一个数字 n,我们将编写一个程序,在 n 行或列上打印图案 G。 例子: 输入:7 输出: *** * * * *** * * * * *** 输入&…

红酒的秘密花园:探索葡萄的种植艺术

在远离城市喧嚣的某个角落,隐藏着一座神秘的红酒秘密花园。这里,葡萄藤缠绵交织,绿叶间闪烁着晶莹的露珠,仿佛在诉说着关于红酒与葡萄种植艺术的古老传说。今天,就让我们一起走进这片神秘的花园,探寻葡萄种…

@amap/amap-jsapi-loader 实现高德地图中添加多边围栏,并可编辑,编辑后获得围栏各个点的经纬度

先上一张效果图 看看是不是大家想要的效果~ ❤️ 希望其中的小点能帮助大家,主要看怎么绘制在地图上的代码即可 1.第一步要加入项目package.json中或者直接yarn install它都可以 想必大家应该都会 "amap/amap-jsapi-loader": "0.0.7&qu…

Oracle EBS PO采购订单预审批状态处理

系统版本 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状: 采购订单状态:预审批 采购订单流程报错如下: po.plsql.PO_DOCUMENT_ACTION_AUTH.approve:90:archive_po not successful - po.plsql.PO_DOCUMENT_ACTION_PVT.do_action:110:unexpected error in acti…

Unity In App Purchasing内购校验

1,利用收据验证混淆器 把后台的key填进去,点击自动生成一些文件 2,代码过滤 using UnityEngine.Purchasing.Security;在IAPManager.cs的 public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)增加 #if !UNITY_EDITOR…

Linux—文件内系统与日志分析

目录 一、Linux文件系统 1、inode 与 block概述 1.2、inode内容 1.3、查找inode 1.4、inode故障处理 2、硬盘分区后的结构 3、访问文件的流程 4、文件恢复 4.1、恢复ext3格式文件 4.2、恢复 xfs 格式文件 二、Linux日志文件 1、日志的功能 2、日志的默认位置 3、日…

第一百四十二节 Java数据类型教程 - Java字符数据类型

Java数据类型教程 - Java字符数据类型 Character类的一个对象包装一个char值。 字符类包含isLetter()和isDigit()方法来检查字符是否为字母和数字。 toUpperCase()和toLowerCase()方法将字符转换为大写和小写。 该类提供了一个构造函数和一个工厂valueOf()方法来从char创建对…

高精度定位技术:赋能电网智能化转型的新引擎

在当今社会,电力作为经济发展的血脉,其稳定高效运行对于国家能源安全与社会发展至关重要。随着科技的飞速进步,高精度定位技术正逐步渗透至电网管理的各个环节,成为推动电网智能化转型的关键力量。本文将深入探讨高精度定位技术在…

联合查询(多表查询)

多表查询是对多张表的数据取笛卡尔积(关联查询可以对关联表使用别名) 数据准备 insert into classes(name, desc) values (计算机系2019级1班, 学习了计算机原理、C和Java语言、数据结构和算法), (中文系2019级3班,学习了中国传统文学), (自动化2019级5…

【java计算机毕设】美容院管理系统 项目源代码MySQL springboot vue html maven+文档 前后端可分离也可不分离

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】美容院管理系统 项目源代码MySQL springboot vue html maven文档 前后端可分离也可不分离 2项目介绍 系统功能: 美容院管理系统包括管理员、用户俩种角色。 管理员功能包括个人中心模块用于修改…

起飞,纯本地实时语音转文字!

简介 偶然在 github 上翻到了这个项目 https://github.com/k2-fsa/sherpa-ncnn 在没有互联网连接的情况下使用带有 ncnn 的下一代 Kaldi 进行实时语音识别。支持 iOS、Android、Raspberry Pi、VisionFive2、LicheePi4A等。 也就是说语音转文字可以不再借助网络服务的接口&am…

为什么技术合作伙伴必须获得 ISO 27001 认证

在当今的数字环境中,强大的安全措施的重要性怎么强调都不为过。 即使是像 Snowflake 这样的巨头,也很少有一天不出现重大漏洞,据《连线》报道,这可能是历史上最大的漏洞之一。 此外,98.3%的组织与至少一家第三方供应商…

【公益案例展】四川农担x中电金信——大数据智能风控平台建设

‍ 中电金信公益案例 本项目案例由中电金信投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2024中国数据智能产业最具社会责任感企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 1、外部经济环境带来的挑战 近几年经济发展和市场需求的挑…

关于5G和卫星

手机,已经串联起了我们生活中的一切环节。我们随时随地拿出手机,都能畅快地上网。 这一切是如此地理所当然,以至于我们甚至想不到这样不可思议的问题: 移动通信网络真的无处不在吗? 我们都知道,地球虽叫…

企业级监控系统Zabbix

文章目录 Zabbix介绍Zabbix架构Zabbix serverZabbix agentZabbix proxy Zabbix Server的安装Zabbix Agent的安装监控主机流程zabbix_get自定义模板和监控项实战用户登录数监控1.指定监控项命令2.重启Agent服务3.在Server上创建监控项4.测试监控项5.查看监控项图形 故障自愈实现…

轮廓检测(python和c++实现)

利用轮廓检测,我们可以检测物体的边界,并在图像中轻松定位。这通常是许多有趣应用的第一步,如图像前景提取、简单图像分割、检测和识别。 无人看管物体检测:公共场所的任何无人看管物体一般都被视为可疑物体。一种有效而安全的解…

农作物生长环境的远程监控与智能调控

农作物生长环境的远程监控与智能调控 农作物生长环境的远程监控与智能调控技术,作为现代农业科技的核心组成部分,正逐步革新传统农业的生产模式,推动农业向精准化、智能化转型。这一技术体系综合应用了物联网、大数据、云计算以及人工智能等…

医疗器械进销存软件 专业合规的医疗公司器械出入库管理软件

财务管理:财务档案统一管理,有利于科学管理企业资金 财务管理:发票关联业务单据,业财融合,加速财务数字化转型 财务管理:提供收付款功能,加快企业应收账款的回收,降低付款的资金浮…