功夫都在报表外-漫谈报表性能优化

2023-12-12 02:38

本文主要是介绍功夫都在报表外-漫谈报表性能优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第3期:封面图片

应用系统中的报表,作为面向业务用户的窗口,其性能一直被高度关注。用户输入参数后都希望立即就能看到统计查询结果,等个十几二十秒还能接受,等到三五分钟的用户体验就非常恶劣了。

那么,报表为什么会慢,又应当从哪里入手进行性能调优呢?

数据准备

当前应用中的报表大都用报表工具开发,当报表响应太慢时,不明就里的用户就会把矛头指向使用报表工具的开发人员或者报表工具厂商。其实,大多数情况报表的慢只是个表现,背后的原因是数据准备太慢,在数据进入报表环节之前就已经慢了,这时再去优化报表开发或压迫报表工具并没有用处。

报表是给人看的,人类视力限制不可能查看过多数据,也就没有大数据的呈现需求。报表工具为了直观而采用的状态式计算模型,也不适合实现有复杂过程的计算。报表环节不应当也无能力解决大数据和复杂计算问题,只要处理小数据的摆位和简单计算,这不会耗用太多时间。

八成左右的报表慢是因为数据准备造成的。报表呈现的数据量虽然小,但涉及的原始数据量可能巨大,把大数据汇总和过滤成小数据需要很长时间;复杂计算也是类似,主要时间消耗在数据准备阶段。数据准备的优化是报表提速的关键。

1. 优化数据准备代码:一般是SQL(或存储过程),某些时候是应用程序的代码(涉及非数据库或多数据库时);

2. 数据库扩容:数据量大,代码不能再优化时,还可以扩容数据库,比如采用集群方案;

3. 采用高性能计算引擎:传统数据库在实现某些运算时性能较差或成本太高,可以更换为其它计算机制;

数据计算

报表环节本身计算性能差的情况相对少,但也是有的。

一个典型的场景是多源关联报表,即把多个二维数据集按某个主键对齐呈现,有时可能还需要分组汇总。报表工具要求把计算都写进单元格,这样只能用数据集过滤来描述本格和其它数据集的关联,类似ds2.select(ID==ds1.ID)的表达式。这个运算复杂度是平方级的,在数据量不大时也无所谓,但数据量稍大(几千行)且涉及数据集较多时,性能就会急剧下降,从几秒到几十分钟都有可能。

如果我们把这个运算移到报表外,在数据准备阶段时处理,就可以大幅度提升性能。如果数据来自同一个数据库,那么用SQL写JOIN语句就可以了,如果数据集来自多库或者希望减轻数据库计算压力,也可以在外部实现HASH JOIN算法。HASH JOIN算法可以整体地看待几个数据集,效率比报表工具采用的过滤式关联要高得多,几千行规模时几乎是零等待。

报表计算性能差虽然发生在报表环节本身,但经常却要在报表外去解决。

其它类似场景还有,如带部分明细行的分组汇总表,表现出来是由于报表环节处理数据量大导致运算变慢,而解决方法也是把运算移到报表外。

数据传输

报表还有个慢的瓶颈在于数据传输。

目前很多应用都是J2EE架构的,采用的报表工具也是Java写的,这时访问数据库都要用JDBC接口。然而,某些常用数据库的JDBC驱动性能很差(这里就不点名了),取出数据量稍多(几万行)时就会有明显的等待感。这就导致一个无奈的现象:数据库压力很轻计算很快,报表端计算也不算复杂,但报表仍然很慢。

无论应用开发商还是报表工具厂商都没办法改变数据库的JDBC驱动,只能在外面想办法。经过多次实验,我们发现启用多线程并行取数就能获得数倍的性能(前提是数据库负担轻)。但是,目前还没有报表工具直接提供了并行取数的功能(由于数据分段方法和数据库及取数语法相关,需要代码控制,也不容易做成报表功能),这个方案仍然要在报表环节外的数据准备阶段来实施。

可控缓存

把近期访问过的报表缓存起来,短时间内再次访问同参数的报表时可以不必计算而直接返回,显然这能改善用户体验。很多报表工具也都提供有缓存功能,不过并不细致,缓存只能针对整个报表,而且各个报表的缓存是无关的。在报表外下点功夫可以实现控制力度更细致的缓存功能:

1. 部分缓存。有些报表、特别是常见的多源报表,其中大部分数据相对稳定(历史数据),只有小部分数据时效性差(当期数据)。而整个报表的缓存的有效期只能以较短的为准,这样会导致报表经常被重算。如果能只缓存部分数据,就能延长这部分缓存的生命期,从而减少计算量。

2. 缓存复用。不同的报表可能引用到同样的数据,而互相无关的报表缓存机制则会迫使这些报表多次重复计算同样的数据。如果能让某个报表引用到其它报表已经计算出来的缓存数据,也能有效减少计算量。

这些复杂的缓存控制需要编写代码来实现,不容易在报表工具中提供,但在可编程的数据准备阶段实施却相对容易。

清单列表

前面说过,报表和大数据的直接关系并不大。甚至可以说老是喊大数据报表的厂商多半是忽悠。

不过有一种清单列表确实是大数据报表。清单列表在金融行业经常碰到,把一段时间的交易清单列出来。其特点是数据量特别大,可能会有几千上万页,不过计算会相对简单,经常只是罗列,最多有些按页按组的汇总。

报表工具为了处理灵活的格间运算,一般都会采用全内存方式。这样,把清单列表加载进报表工具时,会大概率出现内存溢出;而且太大数据量全部取出并加载也需要很长时间,用户难以容忍。

容易想到的办法是边读取边呈现,每次只呈现一页,不会溢出;读满一页后立即呈现,用户不会有太强的等待感。数据库都提供有游标可以逐步读出数据,但用户可能在前端翻页,这还需要高速随机按页(行)取数的能力。数据库就没有这种接口了,用条件过滤取数不仅很慢,而且还由于数据可能仍在更新而不能保证报表在生命周期内的数据一致性。

结果还是要在数据准备阶段解决。两个异步线程:一个负责从数据库取数并缓存到外存(假定数据量大内存装不下),另一个接受前端请求从缓存中按页(行)取出数据返回。

这篇关于功夫都在报表外-漫谈报表性能优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/482943

相关文章

mysql线上查询之前要性能调优的技巧及示例

《mysql线上查询之前要性能调优的技巧及示例》文章介绍了查询优化的几种方法,包括使用索引、避免不必要的列和行、有效的JOIN策略、子查询和派生表的优化、查询提示和优化器提示等,这些方法可以帮助提高数... 目录避免不必要的列和行使用有效的JOIN策略使用子查询和派生表时要小心使用查询提示和优化器提示其他常

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

MySQL不使用子查询的原因及优化案例

《MySQL不使用子查询的原因及优化案例》对于mysql,不推荐使用子查询,效率太差,执行子查询时,MYSQL需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响,本文给大家... 目录不推荐使用子查询和JOIN的原因解决方案优化案例案例1:查询所有有库存的商品信息案例2:使用EX