我们是如何把查询10万条数据从16s优化到1s以内的?原创
金蝶云社区-huhu115
huhu115
7人赞赏了该文章 64次浏览 未经作者许可,禁止转载编辑于2024年10月31日 11:03:57
summary-icon摘要由AI智能服务提供

项目重构前发现加载9万条商品需16秒,影响客户体验。团队参考竞品,决定分批请求和按需获取数据,优化前端请求逻辑和SQL查询,并利用后端多线程机制分块查询,同时瘦身返回体。最终请求时间降至1秒左右,百万条数据请求时间12秒左右。

项目终于要重构了,重构前需要对现有逻辑进行整理,其中发现一个必须要整改的点,加载所有商品,如果客户的商品达到9万条,则查询时间相当离谱,看截图

image.png

足足需要16s,也就是说客户在访问我们系统时,需要16s之后选商品才是全的。


既然发现了这个问题就要解决,那怎么解决呢?

领导给了我们一个好的idea,参考下竞品,看竞品是怎么做到的

ok,三人行,必有我师焉,搞起,把竞品的请求方式摸底下,还真别说,竞品的获取商品速度就是快,当然也和商品数量没有这么多有关

但是,竞品给了我们一个很好的思路:

    获取商品不要一次返回所有数据,可以只返回单表数据,其他数据可以在需要展示时,按需获取

这个想法非常好,我们决定试一下,当然在试这个之前,我们还有一些其他优化可以做:

前端分批请求

    不要一次把所有数据全请求完,充分利用浏览器的并发请求机制,浏览器发起的请求最大并发数量一般都是6~8个,所以可以一次请求一万条数据,请求9次,如此可以节省大量的时间,如下图可见,由之前的16s,已经降到5s左右,大跨度的提升

image.png

前端分批请求的逻辑也非常简单,对请求进行分页,然后把请求塞到数组里,再使用axios.all包一下,就就可以在回调中取得所有接口返回的数据了,顺序也是对的.


5s还是太久了,继续优化

优化sql,去掉关联查询,只保留商品表查询

    查询商品接口仅做商品的查询,其他的如属性、规格、价格的都先不查询,可以在下拉弹窗出现时,滚动触底时补全数据,争取做到极简查询,通过这样一波优化,查询速度又得到了极大的提升,如下图可以看到速度提升到了2.6s左右,又快了一半

    image.png

10万条数据,2.6s左右返回,虽然看着可以了,但是如果是百万商品呢,百万商品查询会不会又耗时很久呢,果不其然,百万商品耗时达到了23s多。

image.png

 

    不行,继续优化,但是sql以及极简了,还能怎么优化呢,总不能换数据库吧,换数据库就不是这么简单的了,继续想

    既然前端可以利用浏览器的并发机制分批次请求,那么后端是否也可以利用多线程机制分块请求呢?答案是可以的(一个后端大佬提供的想法,特此感谢)

后端分块查询数据库   

    前端一次请求一万条,后端再分成5个线程去连接数据库,每个线程查询2000条,请求完后再封装数据返回,

    效果也是明显的,速度提升了有几百毫秒,忘记截图了,尴尬

    优化后,请求时间已经无限接近我们的要求了,但还是有优化空间。

    sql无法优化了,但是返回json可以优化,如果把返回体缩小了,是不是对请求时间也会降下来,于是后端同学立马行动,开始给返回体瘦身。

返回体瘦身

    返回体瘦身又包括两个方面,第一删除无用的字段,只保留必须的6个字段,包括商品id、名称、编码、备注、规格、拼音,其他的就不返回了

    第二方面,使用简写key值,前后端约定a:商品id,b:商品名称,c:商品编码 依次类推

    返回后的数据长这样:

    image.png

    再看下效果,请求后时间有减少吗

    image.png

   请求时间终于降到了1s左右了,虽然会有一些上下浮动,但是有多次跑到了1s以内,基本算达成目标

    再看下百万计的数据请求时间,12s左右,还可以了,毕竟百万计商品的客户屈指可数。

    image.png

    好了,这次优化就告一段落了,接口已经很快了,剩下的大头是前端的了,前端如何保证渲染10万条数据以及百万条数据不卡顿,也是一个挑战。   



图标赞 7
7人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!

您的鼓励与嘉奖将成为创作者们前进的动力,如果觉得本文还不错,可以给予作者创作打赏哦!

请选择打赏金币数 *

10金币20金币30金币40金币50金币60金币
可用金币: 0