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

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

相关文章

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

MySQL中优化CPU使用的详细指南

《MySQL中优化CPU使用的详细指南》优化MySQL的CPU使用可以显著提高数据库的性能和响应时间,本文为大家整理了一些优化CPU使用的方法,大家可以根据需要进行选择... 目录一、优化查询和索引1.1 优化查询语句1.2 创建和优化索引1.3 避免全表扫描二、调整mysql配置参数2.1 调整线程数2.

Java慢查询排查与性能调优完整实战指南

《Java慢查询排查与性能调优完整实战指南》Java调优是一个广泛的话题,它涵盖了代码优化、内存管理、并发处理等多个方面,:本文主要介绍Java慢查询排查与性能调优的相关资料,文中通过代码介绍的非... 目录1. 事故全景:从告警到定位1.1 事故时间线1.2 关键指标异常1.3 排查工具链2. 深度剖析:

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

SpringBoot利用树形结构优化查询速度

《SpringBoot利用树形结构优化查询速度》这篇文章主要为大家详细介绍了SpringBoot利用树形结构优化查询速度,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一个真实的性能灾难传统方案为什么这么慢N+1查询灾难性能测试数据对比核心解决方案:一次查询 + O(n)算法解决