MySQL五千万大表查询优化实战

背景

DBA同事在钉钉发了两张告警截图,作为“始作俑者”的我很心虚,因为刚才是我在管理后台查询数据,结果很久都没出来,并且用多个维度查了N次

问题分析

这是当天上线的功能,完事我立马锁定SQL然后开启排查

# 原SQL,此为分页接口中count部分
SELECTCOUNT( 1 ) 
FROMshop_day_statistics aLEFT JOIN (SELECTshop_id shop_id,statistics_time,merchant_id,GROUP_CONCAT( CONCAT_ws( '-', service_id, service_name ) SEPARATOR ',' ) AS service_name,sum( profit_amount ) profit_amount FROMservice_day_statistics GROUP BYshop_id,statistics_time ) s ON s.shop_id = a.shop_idAND a.statistics_time = s.statistics_time 
WHEREa.statistics_time BETWEEN '2023-09-05 00:00:00.0' AND '2024-10-22 00:00:00.0' AND a.shop_id = 999999;# SQL解释
此SQL中有两张表:shop_day_statistics(5800W)、service_day_statistics(30多万)
下面将用A表来替代shop_day_statistics,B表来替代service_day_statistics
A表与B表的关系是一对多,因业务的需要,故之前在一条SQL上查询得出表结构:
DROP TABLE IF EXISTS `shop_day_statistics`;
CREATE TABLE `shop_day_statistics`  (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',`statistics_time` date NOT NULL COMMENT '统计日期',`group_id` bigint NULL DEFAULT NULL COMMENT '代理商ID',`group_name` varchar(70) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '代理商名称',`shop_id` bigint NULL DEFAULT NULL COMMENT '门店ID',`shop_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '门店名称',`merchant_id` bigint NULL DEFAULT NULL COMMENT '商户ID',`merchant_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '商户名称',`employee_id` bigint NULL DEFAULT NULL COMMENT '员工ID',`employee_name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '员工名称',PRIMARY KEY (`id`) USING BTREE,INDEX `idx_groupid_time`(`group_id` ASC, `statistics_time` ASC) USING BTREE,INDEX `idx_merchantid_time`(`merchant_id` ASC, `statistics_time` ASC) USING BTREE,INDEX `idx_statistics_time`(`statistics_time` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '门店日收益统计' ROW_FORMAT = DYNAMIC;DROP TABLE IF EXISTS `service_day_statistics`;
CREATE TABLE `service_day_statistics`  (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',`statistics_time` date NOT NULL COMMENT '统计日期',`shop_id` bigint NULL DEFAULT NULL COMMENT '门店ID',`shop_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '门店名称',`merchant_id` bigint NULL DEFAULT NULL COMMENT '商户ID',`merchant_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '商户名称',`service_id` bigint NULL DEFAULT NULL COMMENT '服务商id',`service_name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '服务商名称',`profit_amount` bigint NULL DEFAULT NULL COMMENT '服务商收益金额',`gmt_create` datetime NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '服务商日收益统计' ROW_FORMAT = DYNAMIC;

SQL解析


从上图可以了解到几个点

  1. 内层的联表是ALL,也很慢,虽然只有三十多万数据,时间也去到了一秒
  2. 外层A表是ALL,全表扫描非常慢

依次改造

  1. 子查询中是没有带任何条件的,故在B表中新增两个参数:group_id,group_name,并为A B表关联的字段增加索引,在后续查询中将外层的条件(门店商户代理商ID)尽可能的加到子查询中,这样能直接命中索引,无需对B进行全表扫描
  2. 外层A表根据shop_id、statistics_time建立联合索引(shop_id必须放前面,区分度更加高)

改造后SQL及其执行计划

SELECTCOUNT( 1 ) 
FROMshop_day_statistics aLEFT JOIN (SELECTshop_id shop_id,statistics_time,merchant_id,GROUP_CONCAT( CONCAT_ws( '-', service_id, service_name ) SEPARATOR ',' ) AS service_name,sum( profit_amount ) profit_amount FROMservice_day_statistics WHEREstatistics_time BETWEEN '2023-09-05 00:00:00.0' AND '2024-10-22 00:00:00.0' AND shop_id = 99999 GROUP BYshop_id,statistics_time ) s ON s.shop_id = a.shop_id AND a.statistics_time = s.statistics_time 
WHEREa.statistics_time BETWEEN '2023-09-05 00:00:00.0' AND '2024-10-22 00:00:00.0' AND a.shop_id = 99999;

到这个时候就爽了吗,从执行计划上看确实如此,但是我们忽视了这个功能是在web页面上操作的,而操作员可以任何额外条件都不输(只有时间),那执行计划又将非常难看

前端限制

限制管理后台使用人员的操作来达到我们预期的执行计划

  1. 默认任何额外条件不输入时仅允许7天跨度查询
  2. 输入代理商/门店/商户ID(这几个字段都与统计时间有做联合索引)后,时间将会允许拉长跨度进行查询

写到最后

对于一个SQL的优化我感触比较深的是:不能仅从SQL本身去进行优化,而需要结合具体的业务进行权衡从而选择一个合适的方案进行优化,目前项目也到高速上升期,出现了很多大表,未来系统将会有更多的问题,当然这即是问题也是挑战,加油!!!

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

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

相关文章

LED灯具分割系统源码&数据集分享

LED灯具分割系统源码&数据集分享 [yolov8-seg-EfficientRepBiPAN&yolov8-seg-dyhead等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Global A…

Docker SDK for Python 交互

目录 1. 创建 Docker 客户端 2. 列出所有容器 3. 容器内执行命令 4. 启动和停止容器 5. 创建和运行新容器 6. 获取容器日志 7. 删除容器 8. 处理镜像 使用 Docker SDK for Python 进行交互非常方便,可以执行各种操作,如管理容器、镜像、网络等。…

科学化润滑方案:满足不同微型导轨需求的润滑策略!

随着工业4.0时代的到来,自动化、智能化生产已成为制造业发展的主流趋势。微型导轨以其高精度、高刚性、长寿命等优异性能,广泛应用于电子设备、医疗器械、精密仪器等领域。而润滑作为微型导轨性能的重要保障,直接关系到微型导轨的运行效果和寿…

界面控件DevExpress中文教程 - 如何拓展具有AI功能的文本编辑器(一)

本文重点介绍了DevExpress在近年来最热门领域——人工智能(AI)和自然语言处理(NLP)的改进! NLP是人工智能的一个分支,它允许计算机与人类语言进行交互,这包括以有意义/有用的方式理解、解释、生成和回应文本(和语音)的能力。基于NLP的功能允…

Run the FPGA VI 选项的作用

Run the FPGA VI 选项的作用是决定当主机 VI 运行时,FPGA VI 是否会自动运行。 具体作用: 勾选 “Run the FPGA VI”: 当主机 VI 执行时,如果 FPGA VI 没有正在运行,系统将自动启动并运行该 FPGA VI。 这可以确保 FPG…

设计模式——门面模式 | 外观模式

哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的——门面模式。 文章目录 定义通用类图1.通用结构2.优点3.缺点 使用场景注意事项1.一个子系统可以有多个门面2.门面不参与子系统内的业务逻辑 定义 定义:…

为Floorp浏览器添加搜索引擎及搜索栏相关设置. 2024-10-08

Floorp浏览器开源项目地址: https://github.com/floorp-Projects/floorp/ 以下内容同样适用于firefox和大部分基于firefox的桌面版浏览器 1.第一步 为Floorp浏览器添加搜索栏 (1.工具栏空白处 次键选择 定制工具栏 (2. 把 搜索框 拖动至工具栏 2.添加搜索引擎 以添加 搜狗搜索…

双十一买什么?双十一买什么东西最划算?超全双十一购物指南!

双十一即将到来,一年一度的购物狂欢盛宴再度开启!在海量的商品面前,怎样挑选出既心仪又实惠的好物,已然成为大家关注的重点。下面为您呈上一份极为全面的2024年双十一必买清单,助力您轻松购物,收获满满&…

人才画像的重要性,如何打造精准人才画像?

人才画像在人力资源管理中占据重要地位,尤其是在人才招聘环节,它发挥着不可替代的作用,制定精准的人才画像有助于优化招聘和人力资源管理,从而提高组织竞争力和发展潜力。 一、人才画像的重要性 提高招聘精准度:精准…

【无人水面艇路径跟随控制8】(Matlab)USV代码阅读:LOS通过视线引导算法和PID控制器来实现无人水面艇的直线路径跟踪

【无人水面艇路径跟随控制8】(Matlab)USV代码阅读:通过视线引导算法和PID控制器来实现无人水面艇的直线路径跟踪 写在最前面LOS.m代码思路1. **参数初始化**2. **仿真时间设置**3. **仿真主循环**3.1 **视线引导法(LOS&#xff09…

跟李沐学AI:使用注意力机制的seq2seq

动机 机器翻译中,每个生成的单词可能相关于源句子中的不同词。但Seq2sqe模型不能对此直接建模。 简单的Seq2Seq模型存在一个问题,即它将整个输入序列的信息压缩到了一个固定长度的向量中,这可能导致信息丢失,尤其是当输入序列很…

网站建设公司哪家好?好的网站建设公司应该有哪些特别之处?

面对众多的网站建设公司,企业该如何选择呢?如何才能避坑呢?本文将探讨好的网站建设公司应该具备的特别之处 案例,这是最直观的表现,一个好的网站建设公司必然拥有为数众多的的案例展示,且这些案例质量高&a…

分布式事务seata AT和XA性能对比

1. AT模式和XA模式性能对比: AT的阻塞是阻塞在了业务服务层,全局锁。 而XA模式是阻塞在了数据库,对数据库的性能影响很大。 肯定是优选AT,可以提升数据库的性能。 (由于AT模式数据库事务阻塞小,那么同一…

自动化测试中如何高效进行元素定位!

前言 在自动化测试中,元素定位是一项非常重要的工作。良好的元素定位可以帮助测试人员处理大量的测试用例,加快测试进度,降低工作负担。但是在实际的测试工作中,我们常常遇到各种各样的定位问题,比如元素定位失败、元…

Python(十一)-__init__()方法,__str__()方法,__del__()方法

目录 魔法方法 无参__init__()方法 有参__init__()方法 __str__()方法 __del__()方法 魔法方法 魔法方法指的是:可以给Python类增加魔力的特殊方法。有两个特点: (1)总是被双下划线所包围; (2&…

kubernetes 中 pod 的管理及优化

目录 一 kubernetes 中的资源 1.1 资源管理介绍 1.2 资源管理方式 1.2.1 命令式对象管理 1.2.2 资源类型 1.2.3 基本命令示例 1.2.3 运行和调试命令示例 1.2.4 高级命令示例 二 什么是pod 2.1 创建自主式pod (生产不推荐) 2.2 利用控制器管理…

零工市场转型数字化的挑战和机遇

我们的生活因为科技而变的更加方便、便利,例如手机支付、网上购物,那么就目前的就业市场来说,零工市场也面临着数字化转型的挑战和机遇。 零工市场数字化的机遇: 1.通过大数据的计算,极大的提高了零工市场中的匹配效率…

定点数和浮点数的详细介绍(一)定义、范围、位宽

1.定点数 1.1定点数描述 定点数包括定点小数(纯小数)、定点整数(纯整数)、整数和小数位数固定的实数。 1.2定点小数: 小数点默认在符号位后面,首位为符号位,其他为数值位(在用二进制代表小数时,例如0xFF,就表示0.5+0.25+0.125+0.0625+0.03125........) 例如,用…

希亦超声波清洗机值得购买吗?清洁技术之王多维度测评大揭秘!

随着人们生活质量的提升,高质量眼镜愈发受到欢迎,但它们的清洁与保养却常常被疏忽,导致镜片蒙尘受损,影响佩戴者的视觉清晰度。为此,超声波眼镜清洗机作为一种新兴潮流应时而生,以其高效清洁眼镜及珠宝、精…