亲宝软件园·资讯

展开

大数据量下查询显示优化方案小结

浩天之家 人气:2
# 大数据量下查询显示优化方案小结 # 最近工作中,遇到了优化大批量数据查询和显示的问题,数据量在10W级别。经过反复设计和讨论,最终得到优化到了较为满意的效果,在此记录小结下,在解决此类问题中的思考。 ## 问题背景说明 ## 通常情况下,用户查询数据量不超过1千条,但有几个大户,通过某种方式,生成了上万级别的数据,前端未针对大数据量的查询和显示进行优化,导致该界面显示卡顿、白屏、点击无响应、显示总量和实际总量不一致等等问题。 ## 总体思路 ## 大数据量查询和显示,可从以下三个方面来优化: * **定时分批查询** * **缓存中心** * **UI优化** 以上三层分别对应数据层、中间层和UI层,每层优化方案可单独使用,也可以结合使用。建议结合使用。 ### 定时分批查询 ### 数据后台提供的查询指令是支持分页查询的,与其相关的字段有: * 查询方向 **qryDir**, 定位查询方向,1为往下查,0为往上查 * 请求行数 **qryCount**,说明期望查询的个数 * 定位串 **qryPositionStr**, 查询定位串,用于定位查询起点 基于上述三个字段,系统可以实现分页查询功能,但具体到UI层,因为无法获知该用户数据总量,也就无法推导总页数信息,UI层无法以分页形式展示。如果后台提供数据总量字段,那就可方便实现上一页、下一页、最后一页等功能。现有后台没提供总量信息,无法在UI层做分页查询,只在数据层做分页查询。 在数据层做分页查询时,对UI层是透明的。也就是说,当数据层尚未查询完毕时,UI层是不会收到响应,还可以继续操作界面。这里可以优化,同产品讨论以下两种处理方式: * 方案一:本次查询尚未返回,禁止UI层重复查询 * 方案二:本次查询尚未返回,支持UI层重复查询 目前的设计采用方案二,因此需要数据层考虑重复请求的场景。除了重复请求之外,数据层还需要考虑后台限制和缓存管理,小结起来有以下三点: 1. 后台限制 2. 缓存管理 3. 重复查询 下面分别阐述数据层针对上述问题的设计方案。 1. 后台限制 任何后台服务能够提供的功能都是有限制要求的。数据后台对查询指令有单次最大条数和查询频率的限制,具体限制如下: * 单次查询最大请求行数建议1000条 * 查询频率限制在5秒15笔查询,超频查询会报错 为了在不影响后台稳定性的情况下,尽可能快地查询回所有信息。在查询过程中,除了常规的分页查询之外,还额外增加定时查询机制,具体设计为,每连续发起3笔分页查询,等待半秒后,继续查询,循环往复,直到所有查询数据都返回,每次分页查询请求条数设置后台推荐的最大值。上述每3笔休息半秒需要根据后台具体限制来设置,考虑到系统还有其他查询指令在同时进行,设置宽松些比较合适。**要明确这一点,在分页查询过程中触发流量超限错误,那么之前已查询的数据都会无效,要慎重设置定时间隔,宁可慢一点,不能出错。** 2. 缓存管理 此处的缓存指的是数据层的缓存,而不是缓存中心的缓存。此处的缓存用于保存分页查询返回的数据,等到所有查询完毕,再汇总往上传递。这里要注意的点,是要区分以下两种情况: * 由缓存中心主动发起的分页查询 * 由数据层发起的分页查询 上述两种情况,单靠分页查询标志无法区分,需要增加额外的标识信息来区分,在缓存中心需要根据此标志进行查询数据的合并和过滤。 3. 重复查询 当数据层查询尚未完成,又有重复查询的情况,按照场景可分为 * UI层发起新的全量查询 * 缓存中心定时发起增量查询 针对UI层发起新的全量查询,作为数据层有两种应对策略: * 方案一:本次查询尚未完成,拒绝新的查询 * 方案二:本次查询尚未完成,允许新的查询,同时清空上次已查询得到的信息 由于数据层是服务提供方,提供给UI层和缓存中心层使用,由于UI层支持重复查询,缓存中心层支持定时查询,所以数据层采用第二种方案。 针对缓存中心定时发起增量查询,当上一次全量或者增量查询尚未返回时,缓存中心要禁止新的增量查询请求。 ### 缓存中心 ### 为了管理缓存以及提供缓存数据接口,设计缓存中心,它介于UI层和数据层之间,UI层通过订阅数据消息,来获得响应数据。查询中心在查询到数据后,通过发布通知的方式,更新界面数据。 在缓存中心中,对外提供两个公共接口: * ForceRefreshData: 主动重新获取全量数据 * GetDataByAccount:按照账号获取全量数据 在缓存中心内部,通过定时器来触发分页查询。当查询完毕时,通过订阅发布机制向有需要的界面推送数据,推送的数据既包括全量数据,也包括增量数据,便于UI层使用。 在缓存中心处理过程中,增量数据的来源有两处: * 定时增量请求 * 两次全量请求 无论是哪种来源,都需要和已有全量查询结果进行对比,得出增量数据。当数据量很大时,从新的全量查询和已有全量查询中对比获得增量数据,时间复杂度很高,比如全量有5W数据,新的全量有6W数据,那么从6W数据中去掉已有的5W数据,得到增量1W数据,双重循环的话,会操作6W*5W次,可通过`stl::set`结构来加速过滤筛选,其中的`key`设置为可唯一标识数据的属性组合即可。 缓存中心要考虑增量查询和全量查询冲突的问题,也就是说,要考虑以下表格中的四种场景: | 当前的查询场景 | 增量查询 | 全量查询 | | -------- | -----: | :----: | | 增量查询 | 增量-增量 | 增量-全量 | | 全量查询 | 全量-增量 | 全量-增量 | 在具体实现时,建议缓存中心中的增量查询和全量查询复用同个请求,保存一份全量数据成员即可。 ### UI优化 ### UI优化可分为交互优化和刷新优化两个方面,以下分别来描述。 ## 交互优化 ## 为减少可能的重复全量查询,可在UI层提示用户,该界面会主动接受数据推送(实际实现,可能是定时查询、也可以是接收后台主推),无需频繁查询,但不禁止用户主动刷新。 另外的话,在用户主动刷新后,界面增加查询定时器,告知用户已查询耗时时间,已查询到的数据量,该数据量可按照每次查询1000条,根据底层逻辑来大概预估已查询到的数据条数,等到数据层全部查询完毕后,显示最终准确数值。 ## 刷新优化 ## 本次优化是在`Windows`系统上,使用`CListCtrl`控件的`Report`模式来显示数据。刷新优化可以从以下三点出发: * 虚表模式赋值 * 界面数据增量刷新 * 界面显示局部刷新 虚表模式赋值,是MFC中提供的加快列表控件显示速度的方案,具体参见 [CListCtrl虚拟列表技术](https://blog.csdn.net/qq_23992597/articlehttps://img.qb5200.com/download-x/details/83010310),此处不再叙述。 界面增量刷新,是指在UI层维护当前显示内容缓存,当有数据更新时,通过比较更新数据和当前缓存,决定是否更新列表。基于上述缓存中心,可通过增量更新来优化判断流程。 界面局部刷新,是指只针对当前界面显示部分进行刷新,未显示部分不进行刷新。界面局部刷新涉及到的函数有以下三个: * [int GetTopIndex()](https:/https://img.qb5200.com/download-x/docs.microsoft.com/en-us/cpp/mfc/reference/clistctrl-class?view=vs-2017#gettopindex) 获得当前显示区域最顶部Item的位置索引 * [int GetCountPerPage()](https:/https://img.qb5200.com/download-x/docs.microsoft.com/en-us/cpp/mfc/reference/clistctrl-class?view=vs-2017#getcountperpage) 获得当前控件显示区域最多能够显示Item的个数 * [BOOL RedrawItems(int nFirst, int nLast)](https:/https://img.qb5200.com/download-x/docs.microsoft.com/en-us/cpp/mfc/reference/clistctrl-class?view=vs-2017#redrawitems) 重绘位置索引在nFirst和nLast区间中的Item 具体使用很简单,在重绘时,只需要以下两句话搞定: ``` int nFirst = GetTopIndex(); RedrawItems(nFirst, nFirst + GetCountPerPage()) ``` 以上方案实现了**界面显示局部刷新**,配合**虚表模式赋值**和**界面数据增量刷新**,可极大提高在大数据量下的`CListCtrl`刷新显示效果,亲测有效,值得使用。 ## 全文总结 ## 本文总结大数据量下的查询和显示优化方案,主要从数据层、中间层和UI层进行优化,方案设计思路如下: * **数据层的定时分批查询** * 根据后台限制优化定时查询间隔 * 缓存管理 * 考虑重复查询场景 * **中间层的缓存中心** * 支持定时增量查询 * 推送数据既包括全量也包括增量 * **UI层的交互优化和刷新优化** * 交互优化 * 虚表模式赋值 * 界面数据增量刷新 * 界面显示局部刷新 以上是本人在大数据量下查询和显示优化方案的思考,文章可能会有纰漏和错误,欢迎大家在留言中指出来,大家一起讨论学习,共同进步!

加载全部内容

相关教程
猜你喜欢
用户评论