前后端 如何 快速的处理和传输 大数据 ? 您所在的位置:网站首页 前后端如何传数据 前后端 如何 快速的处理和传输 大数据 ?

前后端 如何 快速的处理和传输 大数据 ?

2023-08-04 02:54| 来源: 网络整理| 查看: 265

很长一段时间没有更新博客了。

近日,工作中解决了一个大数据量的传输问题。

工作中遇到的问题

我们有几万 至 几十万条数据,甚至更多的数据需要通过后端处理和传输给浏览器。 这个时候传输的json数据可能有 十几 至 几十兆 的数据量。

java 如何如何快速处理数据,压缩数据。让用户能够快速的看到页面上的数据。

场景限定:服务器性能是固定的、网络带宽也固定要求:服务器处理数据的时间 + 网络io传输的时间 总时间最小。当然js处理这些数据,将其展示到浏览器的时间不计入,其主要的原因是当下的用户个人电脑往往性能足够,可以快速处理这些数据。

作为一个java 开发者,在设计接口的时候我们往往会用对象进行存储数据。 例如:

@Data public class Data { private String field1; private String field2; ... ... } /** * sample interface */ public interface A { public List method(); }

这种方式我们非常乐意去写,而且也非常的容易理解前端和后端的沟通是比较方便的。

但是 这种接口并不适合大数据量的传输,如果我们有十几万条数据(十几万个 Data对象),通过这种方式我们会传输很多冗余的内容。

下面的数据结构 造成的 问题一:重复的字段名称

[ { "field1": "value1", "field2": "value2-1", ... }, { "field1": "value1", "field2": "value2-2", ... }, ... ]

比方说重复的字段名称field1、field2会通过json的方式传输给前端。占用了网络带宽。

造成的问题二:没法压缩字段值中重复的数据

比如上述例子中的 field1如果存在很多的重复值value1 的话,传输过程中也会浪费我们的带宽。

解决 问题一:重复的字段名称

问题一的解决方案很简单,我们可以利用数组这种紧凑的数据结构来去除重复的字段名称;

我们可以把数据结构改造成这样:

"columns":["field1","field2",...] "data":[ ["value1","value2-1",...], ["value1","value2-2",...], ... ]

这种方式在日常工作中也见到过,相信很多开发人员也见过。

在开发过程中我们常常会用Mybatis/MybatisPlus/JPA等数据库持久层框架进行开发,往往我们通过sql得到数据后就直接转换成了一个Bean对象,然后通过Bean再将这种数据转换成上述的格式,但这样明显多了中间一层,实际上是可以避免的,毕竟数据量如果达到十几万以上时会造成额外的 内存 和 性能 开销。

因此建议避免先转换为Bean再转上述结构,应该直接得到上述结构。 怎么实现的,可以多种多样,可以用原生的 jdbc 操作也可以用上述持久层框架的一些高级用法。

解决 问题二:重复的字段值(压缩字段值)

问题二的产生依赖于我们现有的数据特征。

比较适合 数据值重复率高的场景,比方说 "value1" 出现了很多次。那么就有必要压缩这类数据,这样可以大大的减少传输的数据大小。

当然往往这种数据我们可能会想到将其转换为下面的结构

案例一:

[ { "field1": "value1", "field2": ["value2-1","value2-2",...] ... }, ... ]

或者类似的结构 案例二:

[ { "value1": ["value2-1","value2-2",...] ... }, ... ]

总之我们的目的是压缩数据,但是上述数据结构需要权衡一下 java处理数据的时候 + 传输的时间 总值,上述的结构可能会需要 java 额外的转换和处理,消耗总时间未必是一个最佳值(因为我们往往需要结合数据库表的设计,往往这种层级的数据结构的依赖于我们多张表的联表查询得到)。

当然理论上这种结构数据压缩率应该是最高的。上述结构无法做到的一件事情

特殊场景: 以案例一的数据结构为例子:假设我们的 field2 字段是来自数据库中column1 + '-' + column2 得到的,并且colum1的值在数据中出现了非常多的重复。假设column1的值有2种,分别是 value1 和 value2 。如果我们想将这里的重复数据提取出来,起到压缩数据的效果。

如果是在案例一 或者 案例二的数据结构基础上再度提取数据的话并不太好操作。

一旦我们实现了该结构,还要想着如何还原得到我们想要的数据结构。

如果存在3级以上乃至更多级的嵌套数据,虽然做到了数据大小最小,但是需要额外的消耗更多的处理。未必是一种最佳方案。

如何完美解决 java处理时间最短,数据又容易还原!达到理想的总时间消耗最优。

为了要达到 java 处理数据时间最短,我们希望从数据库得到的数据尽可能的少做额外的运算操作。

假设a表

column1column2ZhangSannanLiSinv

假设b表

column1column3column4ZhangSan98100LiSi5059

原先的query我们可能是这样的结构,需要联表查询

select a.column1, a.column2|| '-' || b.column3, b.column4 from table1 as a left join table2 as b where a.column1=b.column1

联表的query结果

column1column2-column3column4ZhangSannan-98100LiSinv-5059

为了压缩数据,首先我们要将query中的拼接逻辑去除,不然传给java的结果已经是字符串,如果还要额外的处理会造成额外的计算开销。 将query改造成下面的结构,去掉字段拼接逻辑

select a.column1, a.column2, b.column3, b.column4 from table1 as a left join table2 as b where a.column1=b.column1

在上述的前提下我们可以通过 java 将数据进行去重操作。另外上述的拼接逻辑需要由后端传给前端,让前端进行拼接。

因此新的数据结构要求如下:

需要将字段拼接的逻辑传给前端(主要原因是该逻辑是固定的,比方说上述案例中 a.column2|| '-' || b.column2,这个规则是固定的)可以利用数组结构省略一些不必要的字段名称对于重复的字段值进行去重

那么我想到的数据结构是这样的

理想的数据结构 { //1、字段的拼接逻辑 "logic":["column1","column2-column3","column4"] //2、 数组下标对应的字段名称 "columns":["column1","column2","column3","column4"] //3、需要压缩的字段,假设我们希望压缩column2和column3字段,则这里面填入 "needCompressedColumn":["column2","column3"] //4、利用数组去除冗余的字段名称,需要结合2 实现,data中数组中的值代表对应的column值 data:[ ["ZhangSan",0,0,100], ["LiSi",1,1,100], ... ] //5、去重后的数据集中放一起 noRepeatData:{ columns2:["nan","nv"], columns3:[98,50] } }

之所以这样设计的目的是 1、还原起来逻辑简单 我们知道:["ZhangSan",0,0,100] 结合"columns":["column1","column2","column3","column4"] 可以很容易得到 下面的结构,根据下标一 一对应即可

{ "column1":"ZhangSan", "column2": 0, "column3": 0, "column4": 100 } 然后再处理一下其中被压缩的字段 column2,column3 可以从noRepeatData中取出对应的column2中下标为0的值是"nan" 同理column3也一样可以得到值98就可以得到我们需要的 { "column1":"ZhangSan", "column2": "nan", "column3": 98, "column4": 100 } 根据拼接逻辑 "logic":["column1","column2-column3","column4"]我们可以很容易的将其转换为 { "column1":"ZhangSan", "column2-column3": "nan-98", "column4": 100 }

这里的逻辑转换可以通过js来完成。

而对于java 只需要做一个去重操作即可。

其逻辑就是遍历 得到的联表结果,一行一行处理,在处理每一个字段时,判断一下该字段是否需要压缩。 如果需要压缩则得到值后看下是否前面已经存入到noRepeatData 中了,如果存入了则只有使用之前的索引,如果没有则添加到noRepeatData中并且得到该值的下标存入 当前行数组。

这样就可以非常快速的得到上述 理想的数据结构。

并且我们可以根据数据特征去配置需要压缩的字段,可以灵活的去使用在任意一个大数据量传输的场景。

可能需要改动的点:

写一个公共的方法,传入query和配置信息。得到我们理想的数据结构js需要写一个公共方法,将上述理想的数据结构还原成原先的数据结构。

query需要稍微变一下

该改动的影响很小,只是改变了java返回的数据结构,js 再加一个公共的数据结构转换的函数即可做到压缩数据的效果。

相信会有非常不错的性能提升。

而且该方法适用于任意需要压缩数据的场景。都可以快速得到压缩后的数据结构,并且可以通过压缩后的结构快速的得到任意你想要的数据结构



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有