大數據量下查詢顯示優化方案小結


大數據量下查詢顯示優化方案小結

最近工作中,遇到了優化大批量數據查詢和顯示的問題,數據量在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筆休息半秒需要根據后台具體限制來設置,考慮到系統還有其他查詢指令在同時進行,設置寬松些比較合適。要明確這一點,在分頁查詢過程中觸發流量超限錯誤,那么之前已查詢的數據都會無效,要慎重設置定時間隔,寧可慢一點,不能出錯。

  1. 緩存管理

此處的緩存指的是數據層的緩存,而不是緩存中心的緩存。此處的緩存用於保存分頁查詢返回的數據,等到所有查詢完畢,再匯總往上傳遞。這里要注意的點,是要區分以下兩種情況:

  • 由緩存中心主動發起的分頁查詢
  • 由數據層發起的分頁查詢

上述兩種情況,單靠分頁查詢標志無法區分,需要增加額外的標識信息來區分,在緩存中心需要根據此標志進行查詢數據的合並和過濾。

  1. 重復查詢

當數據層查詢尚未完成,又有重復查詢的情況,按照場景可分為

  • 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虛擬列表技術,此處不再敘述。

界面增量刷新,是指在UI層維護當前顯示內容緩存,當有數據更新時,通過比較更新數據和當前緩存,決定是否更新列表。基於上述緩存中心,可通過增量更新來優化判斷流程。

界面局部刷新,是指只針對當前界面顯示部分進行刷新,未顯示部分不進行刷新。界面局部刷新涉及到的函數有以下三個:

具體使用很簡單,在重繪時,只需要以下兩句話搞定:


int nFirst = GetTopIndex();
RedrawItems(nFirst, nFirst + GetCountPerPage())

以上方案實現了界面顯示局部刷新,配合虛表模式賦值界面數據增量刷新,可極大提高在大數據量下的CListCtrl刷新顯示效果,親測有效,值得使用。

全文總結

本文總結大數據量下的查詢和顯示優化方案,主要從數據層、中間層和UI層進行優化,方案設計思路如下:

  • 數據層的定時分批查詢
    • 根據后台限制優化定時查詢間隔
    • 緩存管理
    • 考慮重復查詢場景
  • 中間層的緩存中心
    • 支持定時增量查詢
    • 推送數據既包括全量也包括增量
  • UI層的交互優化和刷新優化
    • 交互優化
    • 虛表模式賦值
    • 界面數據增量刷新
    • 界面顯示局部刷新

以上是本人在大數據量下查詢和顯示優化方案的思考,文章可能會有紕漏和錯誤,歡迎大家在留言中指出來,大家一起討論學習,共同進步!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM