前后端性能优化实践(含Java代码部分、数据库部分、React前端部分)

news2024/11/16 3:27:25

最近的一个大屏报表统计的接口查询速度很慢,耗时近一分钟左右,数据量级只是700万左右,但很慢,最后优化到4秒左右,客户还能接受,但其实还可以在优化,先这样吧,简单记录下。这次主要优化的部分数据库和Java代码部分,前端的很少。

一、数据库

优化先从浏览器的接口调用看,查看到耗时近1分钟,根据接口名称查询对应的Java代码,发现代码中存在两个SQL的调用,顺着引用找到SQL语句,一看是两个都是关联查询的SQL,其中一个还是关联了5张表,复制出来后,到SQL端执行,确实很慢。

数据库优化很好用的两个命令是EXPLAINEXPLAIN ANALYZE命令,都是加载查询语句前面,用于分析查询计划查询实际执行情况的。

然后是使用EXPLAIN命令查看查询计划的的信息,判断是否有需要添加或修改的索引。

使用案例:

---只需将 EXPLAIN 关键字加在查询语句开头就行 

EXPLAIN SELECT COUNT(DISTINCT h.id)
FROM test h
JOIN test2 s ON h.id = s.father_id
WHERE s.first_classify = 'QC' ;

执行结果示例

EXPLAIN 命令可以用来分析 SQL 查询语句的执行计划,它返回一组字段信息,提供了有关查询的重要性能指标和执行计划的详细信息。下面是 EXPLAIN 命令返回的字段信息的介绍:

  1. id:查询的标识符,用于标识查询中的每个操作步骤。如果查询有多个操作步骤,id 可能会有多个数字,表示操作步骤的执行顺序。

  2. select_type:操作步骤的类型,表示查询的类型。常见的类型有 SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)、DERIVED(派生表查询)等。

  3. table:操作步骤涉及的表的名称。

  4. partitions:操作步骤使用的分区。

  5. type:访问表的方式,表示查询使用的访问方法。常见的类型有 const(常量表)、eq_ref(唯一索引查找)、ref(非唯一索引查找)、range(范围查找)、index(索引扫描)、all(全表扫描)等。一般来说,访问方法从最好到最差的顺序是:const、eq_ref、ref、range、index、all。

  6. possible_keys:可能应用于该操作步骤的索引列表。

  7. key:实际应用于该操作步骤的索引。

  8. key_len:索引字段的长度。

  9. ref:操作步骤使用的索引字段或常量与表之间的关联。

  10. rows:操作步骤扫描的行数估计。

  11. filtered:操作步骤的行过滤百分比。

  12. Extra:附加信息,提供了关于操作步骤的其他信息,例如是否使用了临时表、是否使用了文件排序等。

这些字段信息可以了解查询的执行计划和性能瓶颈,从而进行性能优化和调整。通过分析这些信息,可以确定是否需要添加索引、优化查询条件、重构查询语句等来提高查询性能。

不同的数据库管理系统(如MySQL、PostgreSQL等)可能会略有不同的字段信息和含义。

关键信息是type类型,尽量少用全表扫描。possible_keys,在适合的字段上加上索引。索引的是使用是用空间换时间。

下面是使用EXPLAIN ANALYZE 命令执行查询结果分析

---只需将 EXPLAIN ANALYZE 关键字加在查询语句开头就行 

EXPLAIN ANALYZE SELECT COUNT(DISTINCT h.id)
FROM test h
JOIN test2 s ON h.id = s.father_id
WHERE s.first_classify = 'QC' ;

执行结果,如果你看不懂,可以直接把查询结果丢给ChatGPT让它给你分析,并逐行注释。

-> Aggregate: count(distinct h.id)  (cost=1193743.16 rows=1) (actual time=4594.609..4594.609 rows=1 loops=1)
    -> Nested loop inner join  (cost=824307.99 rows=3694352) (actual time=0.359..2941.550 rows=1277716 loops=1)
        -> Covering index scan on h using id_idx  (cost=33565.75 rows=257665) (actual time=0.136..76.075 rows=272267 loops=1)
        -> Covering index lookup on s using idx_father_id_first_classify (father_id=h.id, first_classify='F41A01')  (cost=1.64 rows=14) (actual time=0.008..0.010 rows=5 loops=272267)

 

EXPLAIN ANALYZE 命令是一种用于分析 SQL 查询语句执行计划和实际执行时间的命令。它返回的字段信息包括 EXPLAIN 命令的字段信息,同时还包括以下字段:

  1. QUERY PLAN:查询执行计划的详细信息,包括操作步骤、访问方法、索引使用等。

  2. Planning Time:查询规划阶段的时间,表示生成查询执行计划所花费的时间。

  3. Execution Time:查询执行阶段的时间,表示实际执行查询所花费的时间。

  4. Actual Rows:实际扫描的行数,表示查询实际扫描的行数。

  5. Actual Loops:实际循环次数,表示查询实际执行的循环次数。

  6. Actual Startup Time:实际开始执行查询的时间。

  7. Actual Total Time:实际执行查询的总时间。

  8. Actual Time:实际执行查询的时间,以毫秒为单位。

EXPLAIN ANALYZE 命令返回的字段信息可以帮助您更全面地了解查询的执行计划和实际执行情况。通过分析这些信息,可以确定查询的性能瓶颈、优化查询计划、减少查询执行时间等。同时,还可以比较不同查询语句的执行效果,选择性能最佳的查询方式。

最后通过ANALYZE TABLE 命令来优化下对应的表,

---只需将 EXPLAIN TABLE 关键字加在表名开头就行 
ANALYZE TABLE test;

ANALYZE TABLE 命令是用于分析和收集数据库表统计信息的命令。它的主要作用是帮助优化查询性能和执行计划。

ANALYZE TABLE 命令会完成以下任务:

  1. 优化查询计划:通过分析表的统计信息,数据库管理系统可以更准确地估计查询的成本和选择最优的执行计划。

  2. 选择合适的索引:通过分析表的索引长度和数据分布情况,可以判断是否需要创建或删除索引,以及选择合适的索引类型和列顺序。

  3. 优化存储空间:通过分析表的行数和平均行长度,可以估计表的总大小,并根据需要进行存储空间的调整。

  4. 检测表的完整性:通过分析更新时间和自增值,可以检测表的数据是否完整,并及时发现可能存在的问题。

数据库的查询,通过加索引大部分都能解决,在这个过程中善于用ChatGPT来帮助解决很重要。

二、Java程序代码

下面是程序代码的部分,原本的程序代码并不是我写的,打开看了之后,有两个执行查询的代码段是可以同时执行的,所以改成并发执行

程序上改后,接口时间就减少一半了,接口时间来到了4.5秒左右,但其实还是慢。

三、前端React代码

在改改前端,前端的话,可以把这个接口的查询放在最开始执行,以减少用户使用的等待延迟感受。前段端代码就省略了。下次有机会在写吧。

四、总结拓展

性能优化某种意义上是对资源取舍利用的问题。通常是就是空间和时间的互换与取舍。

以下是我收集到的常见的6种互换手段。

1、索引

索引的原理是拿额外的存储空间换取查询时间,增加了写入数据的开销,但使读取数据的时间复杂度一般从O(n)降低到O(logn)甚至O(1)。

在数据集比较大时,不用索引就像从一本没有目录而且内容乱序的新华字典查一个字,得一页一页全翻一遍才能找到;用索引之后,就像用拼音先在目录中先找到要查到字在哪一页,直接翻过去就行了。书籍的目录是典型的树状结构。

2、缓存

缓存优化性能的原理和索引一样,是拿额外的存储空间换取查询时间。Phil Karlton 曾说过:计算机科学中只有两件困难的事情:缓存失效和命名规范。缓存的使用除了带来额外的复杂度以外,还面临如何处理缓存失效的问题。

3、压缩

压缩的原理消耗计算的时间,换一种更紧凑的编码方式来表示数据。对数据的压缩虽然消耗了时间来换取更小的空间存储,但更小的存储空间会在另一个维度带来更大的时间收益。

能减少的就减少:

  • JS打包过程“摇树”,去掉没有使用的文件、函数、变量;

  • 开启HTTP/2和高版本的TLS,减少了Round Trip,节省了TCP连接,自带大量性能优化;

  • 减少不必要的信息,比如Cookie的数量,去掉不必要的HTTP请求头;

  • 更新采用增量更新,比如HTTP的PATCH,只传输变化的属性而不是整条数据;

  • 缩短单行日志的长度、缩短URL、在具有可读性情况下用短的属性名等等;

  • 使用位图和位操作,用风骚的位操作最小化存取的数据。典型的例子有:用Redis的位图来记录统计海量用户登录状态;布隆过滤器用位图排除不可能存在的数据;大量开关型的设置的存储等等。

能删除的就删除:

  • 删掉不用的数据;

  • 删掉不用的索引;

  • 删掉不该打的日志;

  • 删掉不必要的通信代码,不去发不必要的HTTP、RPC请求或调用,轮询改发布订阅;

  • 终极方案:砍掉整个功能。

4、预取

预取通常搭配缓存一起用,其原理是在缓存空间换时间基础上更进一步,再加上一次“时间换时间”,也就是:用事先预取的耗时,换取第一次加载的时间。

当可以猜测出以后的某个时间很有可能会用到某种数据时,把数据预先取到需要用的地方,能大幅度提升用户体验或服务端响应速度。

5、削峰填谷

削峰填谷的原理也是“时间换时间”,谷时换峰时。

削峰填谷与预取是反过来的:预取是事先花时间做,削峰填谷是事后花时间做。就像三峡大坝可以抗住短期巨量洪水,事后雨停再慢慢开闸防水。软件世界的“削峰填谷”是类似的,只是不是用三峡大坝实现,而是用消息队列、异步化等方式。

6、批量处理

批量处理同样可以看成“时间换时间”,其原理是减少了重复的事情,是一种对执行流程的压缩。以个别批量操作更长的耗时为代价,在整体上换取了更多的时间。

  • 前端把所有文件打包成单个JS,大部分时候并不是最优解。Webpack提供了很多分块的机制,CSS和JS分开、JS按业务分更小的Chunk结合懒加载、一些体积大又不用在首屏用的第三方库设置external或单独分块,可能整体性能更高。不一定要一批搞定所有事情,分几个小批次反而用户体验的性能更好。

  • Redis的MGET、MSET来批量存取数据时,每批大小不宜过大,因为Redis主线程只有一个,如果一批太大执行期间会让其他命令无法响应。经验上一批50-100个Key性能是不错的,但最好在真实环境下用真实大小的数据量化度量一下,做Benchmark测试才能确定一批大小的最优值。

  • MySQL、Oracle这类RDBMS,最优的批量Insert的大小也视数据行的特性而定。我之前在2U8G的Oracle上用一些普遍的业务数据做过测试,批量插入时每批5000-10000条数据性能是最高的,每批过大会导致DML的解析耗时过长,甚至单个SQL语句体积超限,单批太多反而得不偿失。

  • 消息队列的发布订阅,每批的消息长度尽量控制在1MB以内,有些云服务商提供的消息队列限制了最大长度,那这个长度可能就是性能拐点,比如AWS的SQS服务对单条消息的限制是256KB。

 

还有与提升并行能力有点关的4中方式:

  1. 榨干计算资源
  2. 水平扩容
  3. 分片
  4. 无锁

参考文献

性能优化的 10 个技巧!(文末送书) 

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

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

相关文章

接口测试学习路线

接口测试分为两种: 测试外部接口:系统和外部系统之间的接口 如:电商网站:支付宝支付 测试内部接口:系统内部的模块之间的联调,或者子系统之间的数据交互 测试重点:测试接口参数传递的正确性&…

进制转换 蓝桥oj Alice和Bob的爱恨情仇

题目 翻译 主要思路 举个例子方便理解 以奇数为底去分解一个奇数,分解次数一定是奇数;以奇数为底去分解一个偶数,分解次数一定是偶数 如果一个堆的分解次数是奇数,就在总分解次数上加1;如果一个堆的分解次数是偶数&…

【高级网络程序设计】Week2-1 Sockets

一、The Basics 1. Sockets 定义An abstraction of a network interface应用 use the Socket API to create connections to remote computers send data(bytes) receive data(bytes) 2. Java network programming the java network libraryimport java.net.*;similar to…

VR Interaction Framework2.0使用

1 按键 ,比如按压下手柄的B键 if (InputBridge.Instance.BButtonDown){print("kkkkkkbbbbb456");} 2抓取某个物体,那么就在要抓取的那个物体上加一些组件,特别是Grabble Unity Events

都2023年了,为什么大家还都在吹捧 Python?

2023 年,Python 还可学吗? 答案当然是可。 近些年间,Python 的火热有目共睹,作为一种功能强大的高级编程语言,在 2018 年的时候它的流行程度就得到了大幅提高。 图源:Stack Overflow 网站编程语言浏览量统…

累计定点160+车型,商汤绝影凭什么领跑规模化量产?

2023广州车展火热进行,智能化技术加速“内卷”。 商汤绝影多款合作量产车型亮相2023广州车展,包括昊铂 GT、传祺ES9、E8系列和本田雅阁、捷途旅行者、极氪X等,全方位呈现在智能驾驶和智能座舱领域的最新成果,以AI“新科技”&…

「树形」样式,数据关联超便捷丨三叠云

树形样式 路径 表单设计 >> 字段属性 功能简介 「表单关联」的数据列表样式支持「树形」样式功能,关联数据选择时通过「树形」的列表方式进行数据选择,提高生产效率。 使用场景: 可以通过树形列表样式展示部门、子部门、成员的树形…

Android开发从0开始(服务)

Android后台运行的解决方案,不需要交互,长期运行。 服务基础框架: public class MyService extends Service { public MyService() { } Override public IBinder onBind(Intent intent) { //activity与service交互(需要继…

美国汽车零部件巨头 AutoZone 遭遇网络攻击

Security Affairs 网站披露,美国汽车配件零售商巨头 AutoZone 称其成为了 Clop MOVEit 文件传输网络攻击的受害者,导致大量数据泄露。 AutoZone 是美国最大的汽车零配件售后市场经销商之一,在美国、墨西哥、波多黎各、巴西和美属维尔京群岛经…

Django项目window环境部署

最近刚好有时间,把前端时间使用django框架开发的音乐网站部署到本地电脑上,在这里记录一下部署过程。 环境配置 Python 3.7.5 Django 3.2.20 Apache 2.4.39 电脑64位 生产环境配置 设置生产环境静态配置 示例如下: # 生产环境静态资源…

windows环境下使用arthas不启动服务替换文件

场景: windows环境,如果现场环境客户正在使用项目,如果要替换项目中的一个class文件,但是又不能重启服务改怎么处理,今天介绍使用arthas中的retransform命令动态替换及使用注意的事项。 环境: windows,arth…

opencv-ORB检测

ORB(Oriented FAST and Rotated BRIEF)是一种图像特征检测和描述算法,结合了 FAST 关键点检测器和 BRIEF 描述子的优点。ORB 算法具有良好的性能,特别适用于实时应用,如目标追踪、相机定位等。 以下是 ORB 算法的一般…

【Python】生死簿管理系统,估值5毛

生死簿管理系统 代码 """ 生死簿管理系统 """ import os import timefile_name data.txtdef main():while True:main_menu()choice (int)(input("请选择: "))if choice in [0, 1, 2, 3, 4, 5, 6, 7]:if choice 0:answer input(&…

2022年MathorCup高校数学建模挑战赛—大数据竞赛A题58到家家政服务订单分配问题求解全过程文档及程序

2022年MathorCup高校数学建模挑战赛—大数据竞赛 A题 58到家家政服务订单分配问题 原题再现: “58 到家”是“58 同城”旗下高品质、高效率的上门家政服务平台,平台向用户提供家政保洁、保姆、月嫂、搬家、维修等众多生活领域的服务。在家政保洁场景中…

WPF面试题中级篇

WPF中级篇[17] 15. 描述下WPF对象完整的层次结构? Object:Object 是 .NET Framework 中所有类的根类。它提供了一些基本的方法和属性,如 Equals、GetHashCode 和 ToString。所有其他类都直接或间接地继承自 Object。Dispatcher:Dispatcher…

蒸蛋器上平台销售UL1026检测报告标准

蒸蛋器是一种采用发热盘通电后,使盘内产生高温蒸汽来快速把禽蛋蒸熟的一种生活小家电。蒸蛋器最大的特点就是快速、简单,并充满乐趣。 深圳ISO 17025实验室办理蒸蛋器亚马逊美国站UL报告办理UL1026测试标准。 UL1026标准是关于蒸蛋器的安全性要求&…

CMS指纹识别方式

一、手工识别 1.robots.txt文件 robots.txt文件我们写过爬虫的就知道,这个文件是告诉我们哪些目录是禁止爬取的。但是大部分的时候我们都能通过robots.txt文件来判断出cms的类型 如: 从wp路径可以看出这个是WordPress的cms 这个就比较明显了直接告诉我们是PageAdmin cms 也…

java堆文件排查

技术主题 在之前的开发的一个项目中,因为程序的一个bug,导致一些引用的对象一直没有回收,从而导致堆内存一直在增大,老年代一直在增大,老年代进行堆积,后来的排查思路是通过dump堆的文件,然后对…

易点易动固定资产管理系统:实现固定资产与财务系统的高效对接

在企业的日常运营中,固定资产的管理和财务账目的记录是两项不可或缺的任务。然而,由于传统的管理方式存在数据孤岛和信息不一致等问题,往往导致工作效率低下和管理混乱。为了解决这一问题,易点易动固定资产管理系统应运而生。该系…

每日一题 2824. 统计和小于目标的下标对数目(简单)

简单题&#xff0c;走流程 class Solution:def countPairs(self, nums: List[int], target: int) -> int:ans 0for i in range(len(nums)):for j in range(i 1, len(nums)):if nums[i] nums[j] < target:ans 1return ans