背景:后台管理系统项目,本次需求迭代:1 新增列表两个字段“商户单号”与“交易单号”,2 支持列表数据全部导出(之前有批量导出excel的功能,但仅导出当前页勾选的条目。本次迭代产品需求是不限于当前页,即所有页数的数据一次性全部导出excel)。
开发:在element-plus的el-table组件中加两个列项“商户单号”与“交易单号”,与后端沟通请求全部数据的方式,后端提供一个查询全部数据的列表接口,前端请求拿到数据后,通过xlsx插件库完成数据导出为excel文件。
问题:前端代码没有问题,但就是导不出excel文件。查看浏览器网络选项,发现请求全部数据的接口超时了,所以没有返回数据。若没有数据,xlsx插件不会导出excel文件。那么,问题就在请求全部数据的接口超时上。
排查:由于导出excel文件的字段有十几个,一开始认为是字段太多,并且所有字段分布在多张表里,数据库查询耗时太久。因此尝试只导出部分字段(测试部分字段时包含了“商户单号”与“交易单号”两个),发现请求依然超时了。经过后端排查,发现“商户单号”与“交易单号”这两个字段是放在单独一张表(下称:单号表),且没有把这两个字段放在每一条记录表里,导致每一条数据需要这两个字段时,都得去单号表查询。如果导出2700条数据,就需要在单号表查询2700次,而由于单号表有接近20W条数据,如果查询命中率50%,也需要耗时2700 * 10W * 每条查询时间,最终导致接口请求超时,拿不到数据因此无法导出excel。
解决:后端在保存前端提交的创建每条记录时,就把“商户单号”与“交易单号”两个字段存到记录表里,那么导出excel时,“商户单号”与“交易单号”两个字段就不需要从单号表里查询了,直接在记录表里取出,从而避免2700 * 10W * 每条查询时间的消耗。
总结:如果本次迭代2个需求是分开的,先上线导出全部功能,再上线新增列表两个字段的话,其实很好发现问题所在。若只上线全部导出功能没有问题,但加入了新增列表两个字段后,请求就超时了,就能够迅速把问题定位在新增列表字段上,从而缩短排查问题的时间。
最终问题解决后,记录了不同数据量的导出情况: 导出2700条数据,excel是1.1M内存,耗时10秒; 导出1.1万条数据,excel是5M内存,耗时45秒; 导出2万条数据,excel是11M内存,耗时72秒。