0%

前后端数据交互之数据压缩

最近做了一个项目的性能优化,觉得这种优化方式比较少见,所以记录一下

事情是这样的:我们项目上某个页面需要一次性能够显示8年时间内所有的销售数据,另外前端还是用了葡萄城公司的wijmo产品做了透视表,以便财务人员查看及分析数据。我们8年的销售数据大概有14万条,通过普通的json传输的总大小为63M,传输速度特别慢,而且最重要的是常常会导致后端服务器挂掉或者500,因此我们顺序的做了以下的优化

第一次优化:更改数据的传输格式

原始的数据格式为是这样的:

1
2
3
4
5
[
{k1: v1, k2: v2},
{k1: v11, k2: v12},
{k1: v21, k2: v22},
]

通过观察我们发现在传输的数据中大量的key是重复的,所以我们第一次优化是把数据改为以下类似于表格的格式:

1
2
3
4
5
6
[
[k1, k2],
[v1, v2],
[v11, v12],
[v21, v22]
]

这次优化下来,传输过程中的数据量变为了36M左右,还是很大的,在网络一般的情况下耗时还是比较长,本地测试是正常状态,但是到了线上,还是会出错,而且是跟没优化前一样,直接会导致服务器挂掉。

第二次优化:分段请求

通过对比发现单次请求耗时较长,我们又试着利用请求并发的特性(chrome下是6个),在第一次优化的基础上进行了第二次优化,如图所示

前端 <> 后端
我需要请求几次? –> 我给你算算
好的,我这就开始请求十次数据 <– 一次给你5000条数据,需要你请求十次
十次请求并发执行 –> 分段返回数据

这次优化结果能好一点,不论是生产环境还是在本地测试,都没有出现服务器挂掉的情况,但是请求时间貌似没有什么变化,耗时还是比较严重。

第三次优化:祭出string table大法

通过查找资料,我们发现string table这种数据结构可以对数据进行大幅的压缩,恰巧Excel的存储就用的是这种数据结构,又恰巧我们的前后端都使用了类Excel的产品(前端SpreadJS,后端Spread.NET),我们就做了一次尝试,把数据通过Spread.NET装进表格中,然后再把表格以blob的形式传递给前端,前端的SpreadJS接收到数据之后就进行了解析以及提取,最后塞给wijmo的透视表,通过测试,数据传输量又一次有了明显的下降,变成了21M左右,传输时间短了很多,但是在后端给Excel填数据的时候,花费了好几秒,后来把Spread.NET进行了升级,最终这个时间也压缩到2秒之内了。

你知道,人总是不满足的,我们在这里尝到了甜头之后,又去仔细的查阅了一遍Spread.NET的文档,发现在导出Excel时有一个紧凑模式(isCompactMod),又尝试性的添加了一个导出的flag,这次数据传输量直接变成了8.5M左右,传输速度又是一次巨幅提升。

总结

我还在想完全不使用Excel,单独的自己弄两个函数来实现string table的读和写操作。不过这次来说,也算是对Excel有了新的认识,现在才知道xlsx文件后缀名改为.rar之后提取出来就是一堆的xml,刚看到这个还是比较惊讶的,真是学海无涯~

参考: