当前位置: 首页 > news >正文

日报表定时任务优化历程

报表需求背景

报表是一个很常见的需求,在项目中后期往往会需要加多种维度的一些统计信息,今天就来谈谈上线近10个月后的一次报表优化优化之路(从一天报表跑需要五分钟,优化至秒级)
需求:对代理商进行日统计
统计数据:门店数量、设备总数、当日订单数/金额/退款/收益、门店七日新增数、30日0订单门店数量
前置约束:未明确标明指定主库操作 以及 事务,则默认代表走 从库 以及 默认事务

先来看看这一版的流程:

// 以下所有查询/统计 均为从MySQL中获取按天 开始 循环(任务调度时可指定日期补偿重跑,防止后续定时任务中断,默认跑昨日数据)1. 获取所有代理商(大几千个)代理商列表 循环开始2. 门店统计2.1    获取代理名下所有门店列表2.2    查询代理近三十天内有订单的门店ID,对比门店列表 得到:30日0订单门店数量2.3    获取代理名下七日新增门店3. 设备总数统计4. 订单统计4.1    统计代理昨日订单数/订单金额/退款(订单/收益 均是千万级表)4.2    统计代理昨日收益代理商列表 循环结束5. 新开事务 且 指定主库5.1    清理对应日期的统计数据5.2    对统计数据进行分批提交(mybatis拼接SQL,千条为一个批次,防止后续当日统计数据过多,导致SQL长度超限)5.3    事务提交
按天 结束 循环

以上流程跑当日耗时大约在4-5分钟,乍一看其实并不慢,但此时距离上线已有九月有余,乍一算这个任务得跑20+小时
不管了,能跑就行,先上线再优化

after a long time
午夜惊醒,这玩意得优化哇,这也太不好用了
-_- 还债的时刻到了

第二版

思考:报表任务里都是一些MySQL查询 以及 内存循环对比,且门店统计那块是嵌套循环查询,订单的查询时间也有点长
带着这些思路去排查,发现几个问题:

  1. 每个代理都需要去查询一遍门店统计信息,这里网络IO次数 = 总代理数量
    若每次50ms * 几千,emm,怎么这么多…
  2. 订单的查询某些代理耗时很高,去看了下索引,emm,1 2 3 4 …8 9 10个索引
    了解到MySQL8.0是基于成本模型来生成执行计划的,那么有可能是索引不完全匹配 或 执行计划偏移,下面贴一下SQL与表当前索引
# 订单统计SQL
SELECTcount( * ) orderTotal,sum( pay_amount ) AS orderAmount,sum( refund_amount ) AS refundTotal
FROMorder 
WHEREagent_id = #{groupId}AND pay_rev_time BETWEEN #{startDate} and #{endDate}    # 这个时间可能会有跨度# 贴下部分索引
uk_order_no            `order_no` ASC
idx_agent_id            `agent_id` ASC
idx_pay_rev_time    `pay_rev_time` ASC
idex_emp            `empower_time` ASC

发现问题,那么就开始一个个尝试改造优化下:

问题一流程优化

1. 分组查询所有代理 门店总数
2. 分组查询所有代理 7 日新增门店数
3. 分组查询所有代理 名下门店总数
4. 分组查询所有代理 近三十天内有订单的门店ID
5. 分组查询所有代理 设备总数
6. 分组查询所有代理 昨日收益金额
按天 开始 循环(任务调度时可指定日期补偿重跑,防止后续定时任务中断,默认跑昨日数据)7. 获取所有的代理代理商列表 循环开始8. 门店统计8.1    内存中 获取代理名下所有门店列表(时间复杂度O(1))8.2    内存中 查询代理近三十天内有订单的门店ID,对比门店列表 得到:30日0订单门店数量(时间复杂度O(1))8.3    内存中 获取代理名下七日新增门店(时间复杂度O(M+N) 代理门店列表 与 有订单门店列表求交集)9. 订单统计9.1    MySQL 统计代理昨日订单数/订单金额/退款9.2    内存中 统计代理昨日收益(时间复杂度O(1))10. 内存中 获取设备总数统计(时间复杂度O(1))11. 新开事务 且 指定主库11.1    清理对应日期的统计数据11.2    对统计数据进行分批提交(mybatis拼接SQL,千条为一个批次,防止后续当日统计数据过多,导致SQL长度超限)11.3    事务提交代理商列表 循环结束
按天 结束 循环

至此重跑,发现统计一天的数据已经达到秒级,这里给到一段真实执行时间

问题二SQL优化

看到这里就会有小伙伴有疑问了,为什么上面 9.1流程 中不采用预先一次性统计所有代理数据呢?
这里是为了引出第二个优化方向,不然这不就结束了嘛~~~

修改后打补丁继续执行,又又又失败了…

# 回顾上面的 订单统计SQL,有两个条件,分别是:agent_id、pay_rev_time
# 而这两个字段也分别有自己的独立索引,分别是:idx_agent_id、idx_pay_rev_time# 那么对于优化器就大概以下几个策略来进行查询:
#     1. 根据 idx_pay_rev_time索引来找到一段时间内数据,然后再根据agent_id 筛选出最终的结果
#     2. 根据 agent_id索引来找到具体代理商的数据,然后再根据pay_rev_time 筛选出最终的结果
#     3. 全表 扫# 在业务中,使用上述几种方式去查询都将不是最优解,而 agent_id、pay_rev_time又是此SQL的必填条件,
# 此时可以为他们创建一个联合索引:ALTER TABLE order ADD INDEX idx_agentid_paytime (agent_id,pay_rev_time);
# 并且在SQL上强制使用此索引,防止执行计划偏移SELECTcount( * ) orderTotal,sum( pay_amount ) AS orderAmount,sum( refund_amount ) AS refundTotal
FROMorder force index(idx_agentid_paytime)
WHEREagent_id = #{groupId}AND pay_rev_time BETWEEN #{startDate} and #{endDate}

后记

问题一流程优化解释

此解题思路实际上是避免了循环查询MySQL,以 一次慢查询 来 优化后续的 多次快查询

但事无绝对,在某些情景下,一次统计的慢查询可能会令系统负载很高,甚至影响到实时业务,那么保持现状:多次快查询 可能会更优

少量多次 与 一次解决,需要根据业务以及系统现状来衡量,有时候快并不是唯一的追求

参考资料

https://dev.mysql.com/doc/refman/8.0/en/cost-model.html
https://www.cnblogs.com/wcwen1990/p/6656611.html

相关文章:

日报表定时任务优化历程

报表需求背景 报表是一个很常见的需求,在项目中后期往往会需要加多种维度的一些统计信息,今天就来谈谈上线近10个月后的一次报表优化优化之路(从一天报表跑需要五分钟,优化至秒级) 需求:对代理商进行日统计…...

excel表格里,可以把百分号放在数字前面吗?

在有些版本里是可以的,这样做: 选中数据,鼠标右键,点击设置单元格格式,切换到自定义,在右侧栏输入%0,点击确定就可以了。 这样设置的好处是,它仍旧是数值,并且数值大小没…...

应用案例 | 商业电气承包商借助Softing NetXpert XG2节省网络验证时间

一家提供全方位服务的电气承包商通过使用Softing NetXpert XG2顺利完成了此次工作任务——简化了故障排查的同时,还在很大程度上减少了不必要的售后回访。 对已经安装好的光纤或铜缆以太网网络进行认证测试可能会面临不同的挑战,这具体取决于网络的规模、…...

【JAVA语言-第20话】多线程详细解析(二)——线程安全,非线程安全的集合转换成线程安全

目录 线程安全 1.1 概述 1.2 案例分析 1.3 解决线程安全问题 1.3.1 使用synchronized关键字 1.3.1.1 同步代码块 1.3.1.2 同步方法 1.3.2 使用Lock锁 1.3.2.1 概述 代码示例: 1.4 线程安全的类 1.4.1 非线程安全集合转换成线程安全集合 1.5 总结 …...

区块链中的加密算法及其作用

区块链技术以其去中心化、不可篡改、透明公开的特性,在全球范围内引发了广泛的关注和讨论。其中,加密算法作为区块链技术的核心组成部分,对于维护区块链网络的安全、确保数据的完整性和真实性起到了至关重要的作用。本文将详细介绍区块链中常…...

微信小程序跳转微信管理平台配置的客服及意见页面

<button open-type"contact" bindcontact"handleContact" session-from"sessionFrom">帮助与客服</button> 不需要路径 在当前小程序中会自动进入 open-type"contact" 其他参数不用修改 只修改这个参数对应表单组件 /…...

灌溉机器人 状压dp

灌溉机器人 题目描述 农田灌溉是一项十分费体力的农活&#xff0c;特别是大型的农田。小明想为农民伯伯们减轻农作负担&#xff0c;最近在研究一款高科技——灌溉机器人。它可以在远程电脑控制下&#xff0c;给农田里的作物进行灌溉。 现在有一片 N 行 M 列的农田。农田的土…...

用于接收参数的几个注解

了解四种主要请求方法的传参格式 GET方法&#xff1a; 参数通常通过URL的查询字符串&#xff08;query string&#xff09;传递&#xff0c;形式为key1value1&key2value2。示例&#xff1a;http://example.com/api/resource?key1value1&key2value2 POST方法&#xf…...

Flask-Login 实现用户认证

Flask-Login 实现用户认证 Flask-Login 是什么 Flask-Login 是 Flask 中的一个第三方库&#xff0c;用于处理用户认证和管理用户会话&#xff0c;它提供了一组工具和功能&#xff0c;使得在 Flask 应用程序中实现用户认证变得更加简单和方便。 如何使用 Flask-Login 1.安装…...

基于WPF的DynamicDataDisplay曲线显示

一、DynamicDataDisplay下载和引用 1.新建项目&#xff0c;下载DynamicDataDisplay引用&#xff1a; 如下图&#xff1a; 二、前端开发&#xff1a; <Border Grid.Row"0" Grid.Column"2" BorderBrush"Purple" BorderThickness"1"…...

股票问题(至多两次购买

class Solution {public int maxProfit(int[] prices) {int[] dpnew int[4];dp[0]-prices[0];//第一次持有dp[1]0;dp[2]-prices[0];//第二次持有dp[3]0;for(int i1;i<prices.length;i){dp[0]Math.max(dp[0],-prices[i]);dp[1]Math.max(dp[1],dp[0]prices[i]);dp[2]Math.max(…...

车辆运动模型中LQR代码实现

一、前言 最近看到关于架构和算法两者关系的一个描述&#xff0c;我觉得非常认同&#xff0c;分享给大家。 1、好架构起到两个作用&#xff1a;合理的分解功能、合理的适配算法&#xff1b; 2、好的架构是好的功能的必要条件&#xff0c;不是充分条件&#xff0c;一味追求架构…...

Springboot集成feign远程调用

需求&#xff1a;在leadnews-wemedia微服务里需要调用leadnews-article微服务的接口。新建一个支持feign调用的名为heima-leadnews-feign-api的模块 heima-leadnews-feign-api的pom文件里导入openfeign依赖 <dependency><groupId>org.springframework.cloud</g…...

构建NFS远程共享存储

nfs-server:10.1.59.237 nfs-web:10..159.218 centos7,服务端和客户端都关闭防火墙和selinux内核防火墙&#xff0c;如果公司要求开启防火墙&#xff0c;那需要放行几个端口 firewall-cmd --add-port2049/tcp --permanent firewall-cmd --add-port111/tcp --permanent firew…...

X9C103SIZT1 数字电位计 IC 10K SOIC-8 参数 应用案例

X9C103SIZT1 是一款数字电位器&#xff0c;属于 X9C103 系列。它是一款100抽头的非易失性数字电位器&#xff0c;阻值为 10 kOhm&#xff0c;封装形式为 SOIC-8。这款器件常用于需要调整电子设备阻值的应用中&#xff0c;如音频设备、电源管理以及传感器校准等。 X9C103SIZT1 的…...

redis深入理解之数据存储

1、redis为什么快 1&#xff09;Redis是单线程执行&#xff0c;在执行时顺序执行 redis单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#xff0c;Redis在处理客户端的请求时包括获取(socket 读)、解析、执行、内容返回 (socket 写)等都由一个顺序串行的主线…...

用20行python写一个最简单的网站

先安装flask框架&#xff0c;cmd命令行 pip install flask&#xff0c;或pycharm -> setting -> project -> python interpreter 搜索安装 # 引入Flask框架 from flask import Flask# 实例化Flask应用 app Flask(__name__)# 定义一个路由&#xff0c;当用户访问网站…...

零基础入门篇①③ Python可变序列类型--列表

Python从入门到精通系列专栏面向零基础以及需要进阶的读者倾心打造,9.9元订阅即可享受付费专栏权益,一个专栏带你吃透Python,专栏分为零基础入门篇、模块篇、网络爬虫篇、Web开发篇、办公自动化篇、数据分析篇…学习不断,持续更新,火热订阅中🔥专栏限时一个月(5.8~6.8)重…...

微服务项目 - SpringBoot 2.x 升级到 SpringBoot 3.2.5,保姆级避坑

目录 一、前言 二、取经之路 2.1、依赖版本情况 2.2、MyBatis-Plus 依赖改变...

【2024亚马逊云科技峰会】Amazon Bedrock + Llama3 生成式AI实践

在 4 月 18 日&#xff0c;Meta在官网上公布了旗下最新大模型Llama 3。目前&#xff0c;Llama 3已经开放了80亿&#xff08;8B&#xff09;和700亿&#xff08;70B&#xff09;两个小参数版本&#xff0c;上下文窗口为8k&#xff0c;据称&#xff0c;通过使用更高质量的训练数据…...

新手也能看懂的SQL注入绕过实战:以BUUCTF的BabySQL靶场为例,手把手教你双写绕过

从零破解BabySQL&#xff1a;双写绕过的艺术与科学 当你第一次接触CTF比赛中的SQL注入题目时&#xff0c;那种既兴奋又困惑的感觉一定记忆犹新。面对BabySQL这样的靶场&#xff0c;新手常会遇到一个典型困境&#xff1a;明明知道应该用union select来获取数据&#xff0c;却发现…...

SAP-ABAP:ABAP Development Tools(ADT)安装配置学习分享教程(四篇连载)第四篇:ADT连接故障排查与环境迁移教程

ABAP Development Tools&#xff08;ADT&#xff09;安装配置学习分享教程&#xff08;四篇连载&#xff09; 第四篇&#xff1a;ADT连接故障排查与环境迁移教程 ADT连不上SAP后端&#xff1f;刚刚还好好的系统突然报错了&#xff1f;换了新电脑要重建整个开发环境&#xff1f…...

避开C2000开发第一个坑:TMS320F28069的InitSysCtrl()函数里,为什么ADC时钟要开一下又关?

TMS320F28069开发揭秘&#xff1a;ADC时钟瞬启瞬闭背后的硬件校准逻辑 在TMS320F28069的InitSysCtrl()初始化函数中&#xff0c;有一段看似矛盾的代码操作&#xff1a;先启用ADC时钟&#xff0c;调用(*Device_cal)()函数后立即关闭。这个"开关ADC时钟"的瞬态操作绝非…...

pcb设计-器件:二极管

一、二极管的介绍 伏安特性曲线 二、二极管的整流功能 由于二极管存在导通压降以及反向截止的特性&#xff0c;对于交流电压&#xff0c;反向电压全部被截止&#xff0c;正向电压的最大值会距离峰值会有0.7v的压降。 在交流电路中&#xff0c;二极管限制了电容不能放电&#xf…...

深入解析:parseInt 到底有几个参数?

&#x1f522; 深入解析&#xff1a;parseInt 到底有几个参数&#xff1f; &#x1f914; parseInt 的签名 parseInt 函数接收 两个 参数&#xff1a; parseInt(string, radix)string (必填)&#xff1a;要被解析的值。如果参数不是字符串&#xff0c;会先转换为字符串。rad…...

AI建站工具推荐:能建站只是开始,实测“全链路变现”才是关键

AI建站工具推荐&#xff1a;能建站只是开始&#xff0c;实测“全链路变现”才是关键 【引言&#xff1a;95%的建站工具都搞错了一件事】 最近我们拆解了市面上17款AI建站工具&#xff0c;发现一个扎心的数据&#xff1a; 超过80%的外贸网站&#xff0c;在上线3个月后依然没有…...

04 - 运行 rocrtst 第一个测试

本文档帮助你成功运行 rocrtst 的第一个测试&#xff0c;并掌握各种运行方式。 1. 运行前检查清单 在运行测试之前&#xff0c;确认以下条件&#xff1a; # ✅ 1. rocrtst64 已构建并安装 ls $ROCM_PREFIX/bin/rocrtst64# ✅ 2. GPU kernel 已编译&#xff08;检查你的 GPU …...

Python 爬虫高级实战:异地多机房爬虫协同采集

前言 随着爬虫业务规模扩张&#xff0c;单机、单机房部署模式逐渐暴露出单点故障、IP 池单一、地域访问延迟高、目标站点区域风控封禁、单机房带宽资源瓶颈等一系列问题。单一机房所有爬虫出口 IP 归属同一运营商、同一地域&#xff0c;极易被目标站点基于地域、IP 段整体封禁…...

从课堂到代码:三大数学可视化工具实战解析

1. 数学可视化工具的选择困境 第一次接触数学可视化工具时&#xff0c;我被各种选项搞得眼花缭乱。作为数学老师&#xff0c;我需要一个能让学生快速上手的工具&#xff1b;作为编程爱好者&#xff0c;我又希望它能支持更复杂的算法可视化。经过多年实践&#xff0c;我发现Desm…...

谷歌排名算法有哪些? 解决AI生成内容不收录的3个操作方案

2024年3月5日&#xff0c;谷歌启动了一场持续45天的核心算法更新。这次调整导致互联网上超过40%的低质量内容被清除。许多依靠软件大批量产出文章的站点&#xff0c;网页收录量在短时间内缩减了九成。单纯依靠算法堆砌出来的文字&#xff0c;在目前的搜索环境下很难获得生存空间…...